编程之美--求子数组之和的最大值

编程之美和编程珠玑上面都有这个经典的例子,珠玑甚至用了第八章整整一章来阐述这个例子,这里对算法的细节就不加以阐述了,(我可以肯定没有这两本书中解释的清楚……),但是我对编程之美的扩展问题进行了求解(珠玑的题目比较深奥,还没有深入解答)。

 

在这里先说扩展问题的第二题:

这里以最后一种算法为基础进行扩展,每次当A[i] > nStart + A[i]时,也就是nStart大于零的时候更新数组的起始index,并且最后输出的起始index应该为该值减一(可以想一想为什么~~);当nAll>nStart的时候更新结束的index。

运行到循环结束就可以得到结果了。这个代码有一个bug,现在还没有调试出来,当输入全部为负数的时候输出结果是不正确的……

 

对于第一个问题,我的思路和书上不一样。根据第二题的解法,我们可以很容易的得到起始的index,然后可以对循环做一个修正,让数组循环两次(不到两次的时候就会停止。),并且做一个记录,到达记录值的时候跳出循环,这个说起来比较复杂,但是代码的实现比较简单。

 

所有的代码如下:

 

//编程之美--最大子数组和 #include <iostream> using namespace std; //function declarations int FindMax1(int *data, int bg, int end);//N^2 solution int FindMax2(int *data, int bg, int end);//another N^2 solution int FindMax3(int *data, int bg, int end);//divide and conquer solution int FindMax4(int *data, int bg, int end);//dynamic programing solution int FindMax5(int *data, int bg, int end);//circus array //can find the index form begin to end of the array int FindMax6(int *data, int bg, int end, int &indexBg, int &indexEnd); int main() { //function pointers int (*Functions[5])(int *, int,int) = {&FindMax1, &FindMax2,&FindMax3,&FindMax4,&FindMax5}; int data[] = {1,-1,2,-3,4,-5,6,7,-8}; int data1[] = {-9,-2,-1,-3,-4,-5,-6,-7,-8}; for (int i = 0; i<5; ++i) {//use four functions cout<<Functions[i](data,0,9)<<endl; } int x,y ; //cout<<FindMax6(data,0,9,x,y)<<"/t"<<x<<ends<<y<<endl; //如果写成这样因为压栈的原因,输出的x和y一定不正确!!! cout<<FindMax6(data,0,9,x,y); cout<<"/t"<<x<<ends<<y<<endl; cout<<"int max = "<<INT_MAX<<endl; return 0; } int inline MaxTreeElement(int a, int b, int c) { return (a>b?a:b) > c ? (a>b?a:b) :c; } int FindMax1(int *data, int bg, int end) {//N^2 solution int maxSum = data[0]; for (int i=bg; i<end; ++i) { int sum = 0; for (int j=i; j<end;++j) { sum += data[j]; maxSum = maxSum>sum?maxSum:sum; } } return maxSum; } int FindMax2(int *data, int bg, int end) {//another N^2 solution //initialize int *realArray = new int[end-bg]; int *cumarr = realArray + 1; cumarr[-1] = data[0]; int maxSum = data[0]; for (int i = bg; i<end; ++i) cumarr[i] = cumarr[i-1] + data[i]; for (int i = 0; i < end; ++i) { int sum; for (int j = i; j< end; ++j) { sum = cumarr[j] - cumarr[i-1]; maxSum = maxSum>sum?maxSum:sum; } } delete []realArray; return maxSum; } int FindMax3(int *data, int bg, int end) {//divide and conquer solution --end;//make the index right if (bg > end) return -INT_MAX-1;//make sure that it cant change the right result if (bg == end) return data[bg]; int mid = bg + (end-bg)/2; int lMax = data[bg], sum = 0; for (int i = mid; i >= bg; --i) { sum += data[i]; lMax = lMax > sum ? lMax : sum; } int rMax = data[end]; sum = 0; for (int i = end; i > mid; --i) { sum += data[i]; rMax = rMax > sum ? rMax : sum; } return MaxTreeElement(lMax+rMax, FindMax3(data,0,mid+1), FindMax3(data, mid+1, end) ); } int FindMax4(int *data, int bg, int end) {//dynamic programing solution int maxSum = data[0]; int maxIndex = 0; for (int i = bg; i<end; ++i) { maxIndex = (maxIndex+data[i]) > data[i] ? (maxIndex+data[i]) : data[i]; maxSum = maxSum > maxIndex ? maxSum : maxIndex; } return maxSum; } int FindMax5(int *data, int bg, int end) {//circus array int maxSum = data[0]; int maxIndex = 0; int indexBg = 0; for (int i = bg; i<2*end-1; ++i) { int j = i%end; if(i>=indexBg-1+end) break; if (maxIndex>0) maxIndex+=data[j]; else { maxIndex = data[j]; indexBg = j; } maxSum = maxSum > maxIndex ? maxSum : maxIndex; } return maxSum; } int FindMax6(int *data, int bg, int end, int &indexBg, int &indexEnd) { int maxSum = data[0]; int maxIndex = 0; for (int i = bg; i<end; ++i) { if (maxIndex>0) maxIndex+=data[i]; else { maxIndex = data[i]; indexBg = i; } if(maxSum < maxIndex) { indexEnd = i; maxSum = maxIndex; } } return maxSum; }

你可能感兴趣的:(编程之美--求子数组之和的最大值)