lintcode循环数组之连续子数组求和

简介:
v 题目:连续子数组求和 II

给定一个整数循环数组(头尾相接),请找出一个连续的子数组,使得该子数组的和最大。输出答案时,请分别返回第一个数字和最后一个数字的值。如果多个答案,请返回其中任意一个。

v 样例

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

v 思路

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](注意是循环数组)就是最大的区间和。

v AC代码
复制代码
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 here
        int 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;
    }
};
复制代码

 

目录
相关文章
|
4月前
LeetCode 1550. 存在连续三个奇数的数组
LeetCode 1550. 存在连续三个奇数的数组
36 0
|
11月前
|
机器学习/深度学习 算法
代码随想录Day02 数组基础2 leetcode T977有序数组的平方, T209 长度最小的子数组,T59 螺旋矩阵II
代码随想录Day02 数组基础2 leetcode T977有序数组的平方, T209 长度最小的子数组,T59 螺旋矩阵II
51 0
|
4月前
|
机器学习/深度学习 算法 测试技术
【排序 贪心】3107. 使数组中位数等于 K 的最少操作数
【排序 贪心】3107. 使数组中位数等于 K 的最少操作数
【排序 贪心】3107. 使数组中位数等于 K 的最少操作数
|
4月前
|
算法
【力扣】4. 寻找两个正序数组的中位数
【力扣】4. 寻找两个正序数组的中位数
|
4月前
leetcode-238:除自身以外数组的乘积
leetcode-238:除自身以外数组的乘积
31 0
|
算法 索引
Leetcode238.除自身以外数组的乘积
Leetcode238.除自身以外数组的乘积
56 0
【LeetCode 327】区间和的个数
【LeetCode 327】区间和的个数
100 0
LeetCode 1464. 数组中两元素的最大乘积
给你一个整数数组 nums,请你选择数组的两个不同下标 i 和 j,使 (nums[i]-1)*(nums[j]-1) 取得最大值。
67 0
|
SQL 算法 数据挖掘
LeetCode015:除自身以外数组的乘积
LeetCode015:除自身以外数组的乘积
LeetCode015:除自身以外数组的乘积
|
SQL 数据挖掘 API
LeetCode014:除自身以外数组的乘积
LeetCode014:除自身以外数组的乘积
LeetCode014:除自身以外数组的乘积