每日一题:最大子数组和

91 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第4天,点击查看活动详情

一、题目描述:

53. 最大子数组和 - 力扣(LeetCode) (leetcode-cn.com)

给你一个整数数组 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 <= 10^5
  • -10^4 <= nums[i] <= 10……4  

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

二、思路分析:

动态规划一般适用于穷举求最值的问题,这道题很明显就是一个动态规划问题。

动态规划的一般解题步骤就是明确状态,明确选择,明确dp定义,明确base case。

这道题,状态就是“最大和”,选择是什么呢,对于数组中的每个元素 i,如果我们以 i 为最大和连续子数组的结尾数字,那么,要凑出也 i 结尾子数组的最大和,无非就两种“选择”:一是和i前面的数组相加,另一种就是自己独立为一个子数组,只有这两种情况才能保证i在子数组的最后,那么 dp[i] 和 dp[i - 1]的状态转移方程就列出来了,dp[i] = Math.max(nums[i], nums[i] + dp[i - 1]),然后我们求出穷举出来的最大值,就是我们要的结果了。

三、AC 代码:

class Solution {
    public int maxSubArray(int[] nums) {
        int n = nums.length;
        if (0 == n) {
            return 0;
        }
        int max = Integer.MIN_VALUE;
        // dp 代表以当前数值结尾的连续子数组的最大值
        int dp = 0;
        for(int i = 0; i < n; i++) {
            dp = Math.max(nums[i], nums[i] + dp);
            max = Math.max(max, dp);
        }

        return max;
    }
}      

参考:

动态规划求数组内的最大值 - 最大子数组和 - 力扣(LeetCode)