Given an integer array, find a continuous rotate subarray where the sum of numbers is the biggest. Your code should return the index of the first number and the index of the last number. (If their are duplicate answer, return anyone. The answer can be rorate array or non- rorate array)this
Give [3, 1, -100, -3, 4]
, return [4,1]
.spa
分析:code
此題是Continuous Subarray Sum的升級版本。對於給定序列A, Continuous Subarray Sum中,子序列爲A{i -> j}, 要求 0 <= i <= j < size(A),此爲經典動態規劃問題。在這裏,子序列除了有以前的形式外,還容許rotate subarray,即子序列容許從尾部延續到頭部,形式爲A{0 -> i, j -> size(A) - 1}。blog
解法一:it
由於容許尾部到頭部造成子序列。一般的想法是把數據copy一份連到尾部。此時咱們能夠用Continous Subarray Sum的解法來作。可是有一點區別,咱們的子序列長度不能超過size(A)。所以,咱們依然能夠用動態規劃來作,不過須要考慮到序列的長度。爲了實現簡便,下面給出一個O(N^2) 非動態規劃的解法,利用了累計數列和條件剪枝。不過最後三個數據仍是會超時。ast
vector<int> continuousSubarraySumII(vector<int>& A) { // Write your code here vector<int> result(2, 0); int n = A.size(); if(n < 2) return result;
//duplicate array vector<int> B(A); B.insert(B.end(), A.begin(), A.end());
//cumsum can help to calculate the sum from B(i) to B(j) with O(1) time vector<int> cumsum; cumsum.push_back(B[0]); for(int i = 1;i < B.size();++i) cumsum.push_back(cumsum[i - 1] + B[i]); int maxVal = B[0], left = 0, right = 0; for(int s = 0;s < n;++s){ //there is no need to start from an negative number, this pruning is useful if(B[s] <= 0) continue; for(int e = s; e < s + n;++e){ int cur = 0; if(s == 0) cur = cumsum[e]; else cur = cumsum[e] - cumsum[s - 1]; if(cur > maxVal){ maxVal = cur; left = s; right = e; } } } result[0] = left%n; result[1] = right%n; return result; }
解法二:class
進一步分析發現,第二種subarray其實和第一種是相關的。咱們能夠經過剪掉最小連續子序列獲得第二種subarray。這裏須要注意當全部數字爲負的狀況。im
vector<int> continuousSubarraySumII(vector<int>& A) { // Write your code here vector<int> result(2, 0); int n = A.size(); if(n < 2) return result; vector<int> posMax(n, 0), posMaxIdx(n, 0), posMin(n, 0), posMinIdx(n, 0); posMax[0] = A[0]; posMin[0] = A[0]; posMaxIdx[0] = 0; posMinIdx[0] = 0; int sum = A[0], maxVal = A[0], minVal = A[0], maxL = 0, maxR = 0, minL = 0, minR = 0; for(int i = 1;i < n;++i){ sum += A[i]; //max subArray if(posMax[i - 1] > 0){ posMax[i] = posMax[i - 1] + A[i]; posMaxIdx[i] = posMaxIdx[i - 1]; }else{ posMax[i] = A[i]; posMaxIdx[i] = i; } //min subArray if(posMin[i - 1] < 0){ posMin[i] = posMin[i - 1] + A[i]; posMinIdx[i] = posMinIdx[i - 1]; }else{ posMin[i] = A[i]; posMinIdx[i] = i; } if(posMax[i] > maxVal){ maxVal = posMax[i]; maxL = posMaxIdx[i]; maxR = i; } if(posMin[i] < minVal){ minVal = posMin[i]; minL = posMinIdx[i]; minR = i; } } int val = sum - minVal; if(val <= maxVal || (minL == 0 && minR == n - 1)){ result[0] = maxL; result[1] = maxR; }else{ result[0] = minR + 1; result[1] = minL - 1; } return result; }