Maximum Subarray

Maximum Subarray

 

Find the contiguous subarray within an array (containing at least one number) which has the largest sum.

For example, given the array [−2,1,−3,4,−1,2,1,−5,4],
the contiguous subarray [4,−1,2,1] has the largest sum = 6.

click to show more practice.

More practice:

If you have figured out the O(n) solution, try coding another solution using the divide and conquer approach, which is more subtle.

方法一:直接暴力破解,时间复杂度可以优化到O(n2)

方法二:使用分治法,假设数组为a[0],a[1],a[2]...a[n-1],将其分成两部分,一部分为a[0],a[1]...a[n/2-1]和a[n/2],a[n/2+1]...a[n-1],则原数组的最大字段和为以下三种情况:

1. 原数组的最大字段和与(a[0],a[1]...a[n/2-1])的相同

2. 原数组的最大字段和与(a[n/2],a[n/2+1]...a[n-1])的相同

3. 原数组的最大字段和跨过其中两个元素a[n/2-1]和a[n/2]

此时总的时间复杂度为O(nlogn),空间复杂度为O(logn)代码如下:

 

 1 class Solution {
 2 public:
 3     int maxSubArray(int A[], int n) {
 4         return maxSub(A, 0, n-1);
 5     }
 6     
 7     int maxSub(int A[], int ibegin, int iend) {
 8         if( ibegin > iend ) return 0;
 9         if( ibegin == iend ) return A[ibegin];  //如果只有一个元素,则直接返回
10         int mid = ibegin + (iend - ibegin) / 2; //取中,防止溢出
11         int il = maxSub(A, ibegin, mid);    //左边部分寻找
12         int ir = maxSub(A, mid+1, iend);    //右边部分寻找
13         int sum = A[mid] + A[mid+1];        //开始寻找跨过a[n/2-1]和a[n/2]的最大值
14         int maxsum = sum;
15         for(int i=mid-1; i>=ibegin; --i) {
16             sum += A[i];
17             maxsum = max(maxsum, sum);
18         }
19         sum = maxsum;
20         for(int i=mid+2; i<=iend; ++i) {
21             sum += A[i];
22             maxsum = max(maxsum, sum);
23         }
24         return max(maxsum, max(il, ir));    //最后输出3者之中的最大值
25     }
26 };

 

 

方法三:动态规划,假设start[i]为a[i],a[i+1]...a[n-1]数组中以a[i]开头的最大字段和,all[i]为a[i],a[i+1]...a[n-1]数组的最大字段和,则有

          start[i] = max{a[i], start[i+1]+a[i]}

          all[i] = max{start[i], all[i+1]}

此时时间复杂度为O(n),空间复杂度也为O(n),不过空间可以优化为O(1),为便于理解,不作优化处理了,代码如下:

 1 class Solution {
 2 public:
 3     int maxSubArray(int A[], int n) {
 4         int start[n];       //start[i]为a[i],a[i+1]...a[n-1]数组中以a[i]开头的最大字段和
 5         int all[n];         //all[i]为a[i],a[i+1]...a[n-1]数组的最大字段和
 6         memset(start, 0, sizeof(start));
 7         memset(all, 0, sizeof(all));
 8         start[n-1] = all[n-1] = A[n-1]; //初始化
 9         for(int i=n-2; i>=0; --i) {
10             start[i] = max(A[i], start[i+1]+A[i]);
11             all[i] = max(start[i], all[i+1]);
12         }
13         return all[0];
14     }
15 };

 

还有一种Kadane算法,相当巧妙,时间复杂度亦为O(n),空间复杂度为O(1),具体请问度娘,代码如下:

 1 class Solution {
 2 public:
 3     int maxSubArray(int A[], int n) {
 4         int ans = -0x3fffffff;  //预处理最小值
 5         int sum = 0;
 6         for(int i=0; i<n; ++i) {
 7             sum += A[i];    //每次计算连续元素
 8             ans = max(ans, sum);   //判断ans是否又变大了
 9             if( sum < 0 ) sum = 0;  //如果sum第一次小于0,立即更新,子数组重新开始
10         }
11         return ans;
12     }
13 };

 

posted on 2014-08-19 16:17  bug睡的略爽  阅读(403)  评论(0编辑  收藏  举报

导航