最大连续子列和问题

给出一个数组求最大的连续子列和
方案1:穷举

    public int findMax(int[] nums) {
        int maxSum = Integer.MIN_VALUE;
        for(int i = 0 ; i < nums.length; i++){
            int thisSum = nums[i];
            for (int j = i + 1; j < nums.length; j++) {
                thisSum = thisSum + nums[j];
                if(thisSum > maxSum){
                    maxSum = thisSum;
                }
            }
        }
        return maxSum;
    }

双重for循环,时间复杂度无疑是O(n^2)

方案2:分而治之

    private int findSubMaxSum(int[] nums, int start, int end){
        if(start == end){
            return nums[start] < 0 ? 0 : nums[start];
        }
        int center = (start + end) / 2;
        //左边部分最大连续子列和
        int leftMax = findSubMaxSum(nums, start, center);

        //右边部分最大连续子列和
        int rightMax = findSubMaxSum(nums, center + 1, end);

        //跨中点最大连续子列和--从中间向左边扫描
        int center2LeftMax = Integer.MIN_VALUE; int center2LeftSum = 0;
        for(int i = center; i >= start; i--){
            center2LeftSum += nums[i];
            center2LeftMax = Math.max(center2LeftMax, center2LeftSum);
        }

        //跨中点最大连续子列和--从中间向右边扫描
        int center2RightMax = Integer.MIN_VALUE; int center2RightSum = 0;
        for(int i = center + 1; i <= end; i++){
            center2RightSum += nums[i];
            center2RightMax = Math.max(center2RightMax, center2RightSum);
        }

        //返回结果 Max(左边部分最大连续子列和, 右边部分最大连续子列和, 跨中点最大连续子列和=(从中间向左边扫描 + 从中间向右边扫描))
        return Math.max(Math.max(leftMax, rightMax), center2RightMax + center2LeftMax);
    }

时间复杂度O(nlgn),推导过程如下
假设求长度为N的数组的最大连续子列和的时间复杂度为T(N),那么
T(N) = 2T(N/2) + c
N
T(N/2) = 左半部分最大连续子列和的时间复杂度 = 右半部分最大连续子列和的时间复杂度
c * N = 跨中点最大连续子列和时间复杂度
继续推导可得
T(N) = 2(2T(N/2^2) + cN/2) + cN = 2^kO(1) + ckN
由算法可知当规模=1时退出递归,则有
N/2^k = 1 --> k = lgN --> T(N) = N + N
lgN --> O(n) = O(n*lgn)

方案3:在线处理

    private int findSubMaxSum(int[] nums){
        int maxSum = Integer.MIN_VALUE; int thisSum = 0;
        for(int i = 0 ; i < nums.length; i++){
            thisSum += nums[i];
            thisSum = thisSum < 0 ? 0 : thisSum;
            maxSum = Math.max(thisSum, maxSum);
        }
        return maxSum;
    }

if(sum(0, n-1) >=0) --> sum(0, n) >= sum(0, n-1)
if(sum(0, n-1) < 0) --> sum(0, n) < num[n] --> 这个时候只需要从num[n]作为起点开始求连续子列和即可
该算法复时间复杂度为O(n)

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 最大连续子列和问题 Q: 给定N个整数的序列{A_1,A_2, …, A_N},求函数 f(i,j)=max{0,...
    Joseph_L阅读 1,612评论 2 2
  • 1 序 2016年6月25日夜,帝都,天下着大雨,拖着行李箱和同学在校门口照了最后一张合照,搬离寝室打车去了提前租...
    RichardJieChen阅读 5,397评论 0 12
  • 以爱的名义 打包 冬的记忆 把所有希望 托付 一场细雨 桃花瓣跌落 幻化成无尽的翠绿 儿童用柳笛 吹奏起春天的序曲...
    淡定方能从容阅读 139评论 1 2
  • 这应该是第三次去上课了。第一次,一人在教室没超过二十分钟。第二次,整课都是在哭泣,以及粘着我,且不依不饶。 此次,...
    渃心阅读 304评论 0 1
  • 就算知道没有结果, 也依然想要, ...
    星辰下的雨阅读 269评论 0 1

友情链接更多精彩内容