夯实算法-11.最大子数组和

200 阅读1分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第19天,点击查看活动详情

题目:Leecode 【难易度:中等】

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

子数组 是数组中的一个连续部分。

示例 1:

输入:nums = [-2,1,-3,4,-1,2,1,-5,4]
输出:6
解释:连续子数组 [4,-1,2,1] 的和最大,为 6 。

示例 2:

输入:nums = [1]
输出:1

示例 3:

输入:nums = [5,4,-1,7,8]
输出:23

提示:

  • 1 <= nums.length <= 105
  • -104 <= nums[i] <= 104  

进阶:如果你已经实现复杂度为 O(n) 的解法,尝试使用更为精妙的 分治法 求解。

解题思路

题目需求是 找出一个具有最大和的连续子数组,返回最大和。到现在做了这么多的动态规划算法的题,就很自然想到用动态规划来解。

按照动态规划流程来解:

  • 确定一个动态连续子数组dp,题目意思是子数组中至少有1个元素。

做多了动规的题,其实很快就会判断出:dp[i]就是以 nums[i] 结尾的子序列的最大和。想到了这一点,那其实就比较简单了,所求的最大值= max(dp[0], dp[1],...,dp[n-1])。就是找出哪个连续子序列和值最大

  • 找出数组dp元素键的递推关系

dp[i]有两个方向可以推出来:

  1. dp[i - 1] + nums[i],即:nums[i]加入当前连续子序列和
  2. nums[i],即:从头开始计算当前连续子序列和

取两者中值更大的,所以dp[i] = max(dp[i - 1] + nums[i], nums[i]);

  • 确定初始值

这里确定初始值还是很简单的,只有一个元素就出来了:dp[0] = nums[0]

代码分析

// 该题的程序代码
public int maxSubArray(int[] nums) {
    int len = nums.length;
    int [] dp = new int[len];  // 定义动态数组dp
    dp[0] = nums[0];  // 确定初始值
    int max = dp[0];
    for (int i = 1; i < len; i++){
        // 获取更大值
        dp[i] = (dp[i-1]+nums[i] > nums[i]) ? dp[i-1] + nums[i] : nums[i];
        if (dp[i] > max) {
            max = dp[i];
        } 
    }
    return max;
}

题目中的提示就表明:nums 数组是非空且元素至少有1个,所以上述代码没有做空判断检测处理。

日常开发中,还必须先做参数检查:nums 是null 或 nums.length=0都要做判断处理

public int maxSubArray(int[] nums) {
    if(nums == null || nums.length == 0) {// nums 是空 或 nums没有元素 
        return 0;
    }
    ...
}

实例运行结果:nums = new int[]{-2, 1, -3, 4, -1, 2, 1, -5, 4}

Snipaste_2022-08-18_17-24-15.png

掘金(JUEJIN)  一起分享知识, Keep Learning!