給定一個整數循環數組(頭尾相接),請找出一個連續的子數組,使得該子數組的和最大。輸出答案時,請分別返回第一個數字和最后一個數字的值。如果多個答案,請返回其中任意一個。
?給定?[3, 1, -100, -3, 4]
, 返回?[4,0]
.
1.如果不是循環數組,求解連續子區間和的思路如下: 首先設一個累加變量和sum和最大值變量maxN,[ld, rd]表示當前正在累加的區間,[lt,rt]表示最大和的區間。從左邊開始一直累加,并初始當前區間[ld, rd]的左右兩端的值。如果在累加之前發現sum<0,那么更新sum為當前的要累加的數字,并且重置新的區間左右兩端的值(即[ld, rd]的值)。另外在累加的過程中,如果sum的值大于maxN,更新maxN的值,并且更新最大值區間(即[lt, rt]改變成[ld, rd])。
2.現在是循環數組,最大和的區間可能會出現在數組的兩端,也就是數組的左邊一段和數組的右邊的一段組成。那么中間的那一部分就是區間和最小的部分。假設一下左端區間[l1, r1]和右端區間[l2, r2]組成最大和的區間,如果[r1+1, l2-1]不是最小和區間,那么存在區間[lx, rx]的和比[r1+1, l2-1]區間和更小(其中有lx>r1+1, rx<l2-1),那么也就是區間[r1+1, lx-1](或者[rx+1, l2-1])和一定大于0,這樣必然會導致左端區間[l1, r1]區間和 +?區間[r1+1, lx-1]和更大。所以區間[r1+1, l2-1]一定是最小區間和。
如?[-1, 2, -1, 2, -1, 10, -100, 10, 9, 8, 7]
, 這個例子中,最小的區間和是-100,區間[6, 6], 區間[7, 5](注意是循環數組)就是最大的區間和。
class Solution { public:/*** @param A an integer array* @return A list of integers includes the index of * the first number and the index of the last number*/vector<int> continuousSubarraySumII(vector<int>& A) {// Write your code hereint ld=0, rd=0, lt=0, rt=0;int sum = 0, maxN = -0x3f3f3f3f;for(int i=0; i<A.size(); ++i){if(sum < 0){sum = A[i];if(maxN < sum){maxN = sum;lt = rt = i;}ld = rd = i;} else {sum += A[i]; rd = i;if(maxN < sum){maxN = sum;lt = ld;rt = rd;}}}ld = rd = 0;int lx=0, rx=0;int sumx = 0, minN = 0x3f3f3f3f, summ = 0;for(int i=0; i<A.size(); ++i){summ += A[i];if(sumx > 0){sumx = A[i];if(minN > sumx){minN = sumx;lx = rx = i;}ld = rd = i;} else {sumx += A[i]; rd = i;if(minN > sumx){minN = sumx;lx = ld;rx = rd;}}}vector<int> ans;if(summ-minN > maxN && lx>0 && rx+1<A.size()){//兩端組成的區間和最大,并且所有的數不都是負數的情況ans.push_back(rx+1);ans.push_back(lx-1);} else {ans.push_back(lt);ans.push_back(rt);}return ans;} };
?