15.最大子序和

一、题目描述

给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

在这里插入图片描述
在这里插入图片描述

二、解题思路

解题思路一

可以使用暴力破解法,代码中有详细注释,这里也分析一下:

首先依次遍历相加,假设当前求和是A,加上下一个数是A+i

每次加下一个数求的和A+i都要和 i 做一个比较,选出一个最大的来,这是分两种情况来考虑:

当加下一个数求的和(A+i)大于于下一个数 (i) 时,说明最大子序列可能出现在继续加后面的元素中,注意一个点,这里判断的是大于下一个数 (i),而不是大于当前和值A,来分析一下,如果我们判断条件是A+i > A,那么,当这个条件不成立时,说明 i 可能是一个负数使得 A+i 变小了,此时我们要更新初始值从 i 开始重新循环,这是不对的,可能在A这个和中保留了最大值,只是刚好遇到了 i 使得和变小,如果加上 i+1 ,假如此时和值 A+i + (i+1) 能保证有最大子序和呢?不知道你能明白这一点不。

如果我的判断条件是A+i >= i,就是当当前和加下一个数大于下一个数时,这个不成立的条件是 i 前面的数加上我本身的和都比我小,那前面的数就没必要作为最大子序列中的值了,直接以我为起点计算就行,这样的判断条件就避免的上面的情况,就是当A+i 变小了,不会重新从 i 开始,仍然会保留A+i求和的部分,所以这里的判断条件A+i >= i才是对的。

解题思路二

这道题的普遍思路是动态规划求解,动态规划的是首先对数组进行遍历,当前最大连续子序列和为 sum,结果为 ans。
如果 sum > 0,则说明 sum 对结果有增益效果,则 sum 保留并加上当前遍历数字
如果 sum <= 0,则说明 sum 对结果无增益效果,需要舍弃,则 sum 直接更新为当前遍历数字
每次比较 sum 和 ans的大小,将最大值置为ans,遍历结束返回结果
时间复杂度:O(n)

三、代码演示

代码演示一

class Solution {
    public int maxSubArray(int[] nums) {
        /*
            暴力破解,利用两个变量,一个记录最大和,一个记录当前遍历的元素求和
        */
        //记录元素的求和
        int current_num = nums[0];
        //记录所有和中的最大值
        int max_num = current_num;
        for(int i=1; i<nums.length; i++){
            /*
            判断当前序列加上下一个元素的值大于下一个元素,表明最大子序列可能出现在后续序列中,记录此时的最大值
            */
            if(current_num+nums[i]>nums[i]){
                //更新最大子序列元素和
                current_num += nums[i];
                //更新最大和值
                max_num = Math.max(max_num, current_num);
            }else{
                /*
                    这种情况是当当前的最大子序列和小于下一个元素时,那么就要将下一个元素作为当前
                    子序列的起始点值
                */
                int m = Math.max(max_num, current_num+nums[i]);
                max_num = Math.max(m, nums[i]);
                //更新起始点
                current_num = nums[i];
            }
        }
        return max_num;
    }
}

代码演示二

class Solution {
    public int maxSubArray(int[] nums) {
        int ans = nums[0];
        int sum = 0;
        for(int num: nums) {
            if(sum > 0) {
                sum += num;
            } else {
                sum = num;
            }
            ans = Math.max(ans, sum);
        }
        return ans;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值