剑指offer:连续子数组的最大和

本文探讨了寻找连续子数组最大和的算法实现,通过遍历和动态规划两种方法进行详细解析,阐述了如何有效避免负数累加导致的不必要计算,提供了清晰的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.题目

在这里插入图片描述

2.解法 1(遍历)

刚开始的思路是:

  • 假设有这样一个数组,为了防止第一个值为负数,所以 max = add = array[0]
    {1,-2,3,10,-4,7,2,-5}

  • 每进行一次累加,都需要判断add是否大于max值,若大的话直接替代
    这一步是包括了数组元素值为正负两种情况:
    - if(array[i] < 0){ if (add > max) max = add}
    如果此时该数组小于0,需要保存最大值,也需要add大于max值。
    -if(array[i] < 0) 如果为正,也需要判断
    所以就不需要判断正负了

  • 如果add值加的过程中小于数组元素值,那么就不需要加了,直接从该元素值开始。
    例如 1+ (-2) + 3 = 2 2 < 3,那么就从3开始。
    代码为:

public class Solution {
    public int FindGreatestSumOfSubArray(int[] array) {
        if (array == null || array.length == 0) {
            return 0;}

        int max = array[0];
        int add = array[0];

        for(int i = 1; i < array.length; i++){
        
            add += array[i];

            if(array[i] > add){
                add = array[i];
            }
            if(add > max){
                max = add;
            }
        }
        return max;
    }
}

以上方法不管元素是正是负都会加,除非有一个if(array[i] > add)

  • 假设有 -1 -2 -3 -4 -5,第一个元素就是最大值,但是程序还是往后一直加
    所以说需要进行判断add
  • 如果add <= 0 了,如果后一个元素为负值,那么结果更小了,如果后一个元素为正值,那么也会使结果更小, 那就直接从此时的array[i]重新开始
    假设add > 0 那么就加上此时的array[i]

此时代码为

public class Solution {
    public int FindGreatestSumOfSubArray(int[] array) {
         if (array == null || array.length == 0) {
         return 0;}
    
        int max = array[0];
        int add = array[0];

        for(int i = 1; i < array.length; i++){
           
            if(add <= 0){
                add = array[i];
            }else{
                add += array[i];
            }

            if(add > max){
                max = add;
            }
        }
        return max;
        }
    }

解法2:动态规划

以每个数组元素结尾都是一个子数组,所以总能共有n个子数组
下标为0<= index <n
如果f(i-1)<= 0 ,那么加上下一个元素只会使得结果更小,所以从下一个元素直接开始,否则f(i-1) > 0,直接加下一个元素
这个方法和上面的思路一样,都是从add为正为负考虑问题

public class Solution {
    public static int FindGreatestSumOfSubArray(int[] array) {

        int len = array.length;
        if (array == null || len == 0) {
            return 0;}

        int[] adds = new int[len];
        // 1.如果只有一个元素,最大值为
        adds[0] = array[0];
        int max = array[0];

        for(int i = 1; i < len; i++){
            // 如果累加的值为负数,那么就没有必要再加了
            if(adds[i-1] <= 0){
                adds[i] = array[i];
            }else{
                adds[i] = adds[i-1] + array[i];
            }
            if(max < adds[i]){
                max = adds[i];
            }
        }
        return max;
    }
}
时间复杂度都为O(n)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值