[LintCode] Continuous Subarray Sum II

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

  Example

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;
    }
相关文章
相关标签/搜索