《程序员面试宝典》14.5 字符串其它问题 面试例题 6:(Page 217)
有一个数组a[n],里面的数只有两种:-1或1。i、j是两个整数,假设0 <= i <= j <= n-1,找出a[i]到a[j]中连续数之和最大的部分(如果最大部分存在相等的,则优先找最短的)。
感觉原文中给出的解法不正确,于是自己实现了一段代码。
思路:从i = 0至n-1,依次求出以a[i]为结尾的序列的最大和maxSum[i],max ( maxSum[i] )即为最大和,其i值就是我们要求的end。同理从i=n-1至0,求一遍最大和,其下标即是我们要求的begin。考虑到会有多个区间符合要求,最后还要对区间跨度进行比较,选择一个跨度最小的。下面是代码:
#include <iostream> using namespace std; //arr :input array //len :array lenth //begin :return the begin index //end : return the end index //function return: max sum int find_range (int *arr, int len, int &begin, int &end) { int *maxSum; int *begins; int *ends; maxSum = (int*)malloc (sizeof(int) * len); //find the ends of the ranges witch has the max sum. maxSum[0] = arr[0]; int max = maxSum[0]; for (int i = 1; i < len; i++) { if (maxSum[i - 1] <= 0) maxSum[i] = arr[i]; else maxSum[i] = maxSum[i - 1] + arr[i]; if (maxSum[i] > max) { max = maxSum[i]; } } int ends_num = 0; for (int i = 0; i < len; i++) { if (maxSum[i] == max) ends_num++; } ends = (int*)malloc (sizeof (int) * ends_num); for (int i = 0, j = 0; i < len; i++) { if (maxSum[i] == max) ends[j++] = i; } //find the begins of the ranges witch has the max sum. maxSum[len - 1] = arr[len - 1]; max = maxSum[len - 1]; for (int i = len - 2; i >= 0; i--) { if (maxSum[i + 1] <= 0) maxSum[i] = arr[i]; else maxSum[i] = maxSum[i + 1] + arr[i]; if (maxSum[i] > max) { max = maxSum[i]; } } int begins_num = 0; for (int i = 0; i < len; i++) { if (maxSum[i] == max) begins_num++; } begins = (int*)malloc (sizeof (int) * begins_num); for (int i = 0, j = 0; i < len; i++) { if (maxSum[i] == max) begins[j++] = i; } //find the minum range [begin, end] having the max sum. begin = begins[0]; end = ends[0]; int begin_i = 0, end_i = 0; int step = end - begin; while (begin_i < begins_num && end_i < ends_num) { while ((begin_i + 1) < begins_num && begins[begin_i+1] <= ends[end_i]) begin_i++; if (step > (ends[end_i] - begins[begin_i])) { begin = begins[begin_i]; end = ends[end_i]; step = end -begin; } if ((begin_i + 1) == begins_num) break; else begin_i++; while ((end_i + 1) < ends_num && ends[end_i + 1] < begins[begin_i]) end_i++; } cout << "Max Sum = " << max << endl; cout << "begin = " << begin << endl; cout << "end = " << end << endl; cout << "step = " << step << endl; return max; } int main () { //Test 1: int arr1[10] = {1,-1,-1,1,1,-1,1,1,1,-1}; int begin,end; find_range (arr1, 10, begin, end); //Test 2: int arr2[10] = {0,0,0,6,0,0,0,0,0,0}; find_range (arr2, 10, begin, end); }