剑指offer解法汇总85-连续子数组的最大和(二) 算法知识视频讲解

该博客介绍了如何在O(n)时间和O(1)空间复杂度内解决找到具有最大和的连续子数组的问题。算法通过维护两个指针start和end,以及当前和sum和历史最大和lastMaxSum,动态更新最大子数组的起始和结束位置。当遇到正数时,累加到sum并可能更新最大和;遇到负数时,更新sum但保留最大和;遇到零时,根据sum是否等于最大和来判断是否更新子数组长度。最终返回最长的最大连续子数组。
摘要由CSDN通过智能技术生成

 原题链接:连续子数组的最大和(二)_牛客题霸_牛客网


描述:

输入一个长度为n的整型数组array,数组中的一个或连续多个整数组成一个子数组,找到一个具有最大和的连续子数组。

1.子数组是连续的,比如[1,3,5,7,9]的子数组有[1,3],[3,5,7]等等,但是[1,3,7]不是子数组

2.如果存在多个最大和的连续子数组,那么返回其中长度最长的,该题数据保证这个最长的只存在一个

3.该题定义的子数组的最小长度为1,不存在为空的子数组,即不存在[]是某个数组的子数组

4.返回的数组不计入空间复杂度计算

数据范围:

1<=n<=10^5

-100 <= a[i] <= 100

要求:时间复杂度O(n),空间复杂度O(n)O

进阶:时间复杂度O(n),空间复杂度O(1)O

解题思路:

解体分为两步,

第一步是保证找出具有最大和的连续子数组。

第二步是如果有相同的连续子数组,找出长度最长的

第一步,找出具有最大和的连续子数组

记录两个指针,一个start,一个end,以及一个当前求和值sum和历史最大求和值lastMaxSum。如果end++依次遍历,如果当前值

array[end]>0时,说明这个值肯定要计入连续子数组的,并且如果当前的sum值大于之前的lastMaxSum,则更新最大连续子数组的范围,然后继续end++遍历。

array[end]<0时,则只更新当前sum值即可,因为当前sum不可能大于lastMaxSum。如果sum<0,则说明之前的连续子数组都可以不要了。则更新start值。重新开始计算。

array[end]==0时,在一步中无需处理。

第二步,找出长度最长的。

加入判断条件,如果sum=lastMaxSum时,要判断当前长度和历史最大值的连续子数组长度。

代码:

public int[] FindGreatestSumOfSubArray(int[] array) {
        int max = -101;
        for (int value : array) {
            if (value > max) {
                max = value;
            }
        }
        if (max < 0) {
            return new int[]{max};
        }


        int[] maxRnage = new int[2];
        int lastMaxSum = 0;

        int start = 0;
        int end = 0;
        int sum = 0;

        //还差一个场景就是后面的sum值相同时长度前面的长
        while (end < array.length) {
            int current = array[end];
            if (current > 0) {
                sum += current;
                //更新最大值
                end++;
                if (sum > lastMaxSum) {
                    lastMaxSum = sum;
                    maxRnage[0] = start;
                    maxRnage[1] = end;
                } else if (sum == lastMaxSum) {
                    //判断长度
                    if ((maxRnage[1] - maxRnage[0]) < (end - start)) {
                        //更新位置
                        maxRnage[0] = start;
                        maxRnage[1] = end;
                    }
                }
            } else if (current < 0) {
                sum += current;
                //全部清空
                end++;
                if (sum < 0) {
                    start = end;
                    sum = 0;
                }
            } else {
                //判断长度
                if ((maxRnage[1] - maxRnage[0]) <= (end + 1 - start) && sum == lastMaxSum) {
                    //更新位置
                    maxRnage[0] = start;
                    maxRnage[1] = end + 1;
                } else if (sum <= 0) {
                    start = end;
                }
                end++;
            }
        }
        start = maxRnage[0];
        end = maxRnage[1];
        int[] ints = new int[end - start];
        System.arraycopy(array, start, ints, 0, end - start);
        return ints;
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

失落夏天

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值