【算法07】求子数组的最大和
题目:输入一个整型数组,数组里面有正数也有负数,数组中的连续一个或者多个整数组成一个子数组,每一个子数组都有一个和,求所有子数组和的最大值。要求时间复杂度为O(n)。
例如:输入数组为{1,-2,3,10,-4,7,2,-5},和的最大子数组为{3,10,-4,7,2},因此输出为子数组的和18。
分析1:一般地,对于在整体集合内寻找满足某一条件子集合问题,最直观也最后理解的方法就是——枚举,求出所有子数组的和,然后比较求出最大的值,即可。然而对于长度为n的数组,它的子数组共有n(n-1)/2个,O(n^2),然后再对于每一个数组求和,时间复杂度为O(n)。因此总的时间复杂度为O(n^3)。效率太低。
分析2:我们知道,对于某个子数组,如果它的下一个数为正数,加上该正数和会增加;而加上一个负数,和会减少;如果当前子数组的话为负数,下一个数不论是正数还是负数,都会使得子数组的和进一步减少,因而这时候应该将子数组和重置为0。基于这种思路我们可以写出如下的代码:
1 #include<iostream>
2 #include<string>
3 using namespace std;
4
5 bool FindMaxSubarray(int *pArray,int arrayLength,int &largestSum)
6 {
7 //无效输入,返回false
8 if(pArray == NULL || arrayLength <= 0)
9 return false;
10
11 int curSum = 0;
12 largestSum = 0;
13 for(int i = 0;i < arrayLength;++i)
14 {
15 curSum += pArray[i];
16
17 //如果当前和小于0,重置为0
18 if(curSum < 0)
19 curSum = 0;
20
21 //找到更大的和,用largestSum保存
22 if(curSum > largestSum)
23 largestSum = curSum;
24 }
25
26 //如果所有的数为都是小于等于0,找到该数组最大的数
27 if(largestSum == 0)
28 {
29 largestSum = pArray[0];
30 for(int i = 1;i < arrayLength;++i)
31 {
32 if(pArray[i] > largestSum)
33 largestSum = pArray[i];
34 }
35 }
36
37 return true;
38 }
39
40 int main()
41 {
42 cout<<"Enter the length of your array:"<<endl;
43 int n;
44 cin>>n;
45
46 cout<<"Enter the numbers in your array:"<<endl;
47 int *p = new int[n];
48 for(int k = 0;k < n;++k)
49 {
50 cin>>p[k];
51 }
52
53 cout<<"your array is:"<<endl;
54 for(k = 0; k < n;++k)
55 cout<<p[k]<<" ";
56
57 cout<<endl;
58 cout<<"the largest subarray sum is:"<<endl;
59 int saveSum;
60 FindMaxSubarray(p,n,saveSum);
61 cout<<saveSum<<endl;
62
63 return 0;
64 }
关于上述代码有两点需要注意:
(1)如果一个数组中的数全部都是负数,那么这时候largestSum还是初始值0,而这时候整个数组的子数组和的最大值就是数组中的最大元素,因而单独拿出来考虑。
(2)关于函数的返回类型,如果按照正常的考虑,函数的返回值应该为整型,即范围子数组和的最大值,然而这样存在一个问题,如果输入本身的无效值,返回什么?返回0,那么如果数组中有0元素,其余全是负数元素,这时候0代表无效输入还是最大值?返回-1?数组中的最大元素真的是-1,怎么办?综上考虑,把子数组和的最大值以引用的方式传入函数的参数,同时让函数范围一个处理正常与否的标志,应该是比较好的方式(何海涛博主的考虑方式很严谨。)
References:
何海涛博客:http://zhedahht.blog.163.com/blog/static/254111742007219147591/
注:
1)本博客所有的代码环境编译均为win7+VC6。所有代码均经过博主上机调试。
2)博主python27对本博客文章享有版权,网络转载请注明出处http://www.cnblogs.com/python27/。对解题思路有任何建议,欢迎在评论中告知。