402. 连续子数组求和

给定一个整数数组,请找出一个连续子数组,使得该子数组的和最大。输出答案时,请分别返回第一个数字和最后一个数字的下标。(如果两个相同的答案,请返回其中任意一个)

 

样例

给定 [-3, 1, 3, -3, 4], 返回[1,4].

 

想清楚这个问题这道题就差不多有解了:“什么时候更新start(第一个数字下标)和end(最后一个数字下标)?”

首先很直接的可以联想到用动态规划来做这个题,用一个vector来存每个位对应的到此位为止的最大子数组和

那么令F[n]表示为到n为止的最大子数组和,可以写出如下update公式

F[n]=max(F[n-1]+A[n], A[n])

如果是取前者,说明F[n-1]>=0, 此时end随n一起更新

如果是后者,说明F[n-1]<0,此时start和end重置为n

 1 vector<int> continuousSubarraySum(vector<int> &A) {
 2         // write your code here
 3         int start=0,end=0,sum=0,max=A[0];
 4         vector<int> res(2,0);
 5         vector<int> record;
 6         record.push_back(A[0]);
 7         for(int i=1;i<A.size();i++){
 8             if(record[i-1]<0){
 9                 record.push_back(A[i]);
10                 start=i;
11                 end=i;
12             }
13             else{
14                 record.push_back(A[i]+record[i-1]);
15                 end=i;
16             }
17             if(record[i]>max){
18                 max=record[i];
19                 res[0]=start;
20                 res[1]=end;
21             }
22         }
23         return res;
24     }

这样做的话,空间复杂度就上去了,这方面可以优化一下

我们用sum作为一个累加器,当sum为负的话,显然我们不应该继续累加了,因为不管怎样不可能得出更大的和,start应该重置到加到sum为负的后一个数

对于end,只要sum不为负,end就跟着加到sum上的数走

 1 vector<int> continuousSubarraySum(vector<int> &A) {
 2         // write your code here
 3         int start=0,end=0,sum=0,max=INT_MIN;
 4         vector<int> res(2,-1);
 5         for(int i=0;i<A.size();i++){
 6             if(sum<0){
 7                 sum = A[i];
 8                 start = i;
 9                 end=i;
10             }
11             else{
12                 sum+=A[i];
13                 end=i;
14             }
15             if(sum>max){
16                 max=sum;
17                 res[0]=start;
18                 res[1]=end;
19             }
20         }
21         return res;
22     }

 

 

posted @ 2018-01-18 11:56  三人木君  阅读(285)  评论(0编辑  收藏  举报