【DP】LeetCode 53. 最大子数组和

题目链接

53. 最大子数组和

思路

分析动态规划题目的时候只需要考虑最后一个阶段,因为所有的阶段转化都是相同的,考虑最后一个阶段容易发现规律

在数组的动态规划问题中,一般 dp[i] 都是表示以 nums[i] 为结尾的状态;dp[i][j] 分别表示 以 nums1[i]nums2[j] 为结尾的状态,以此类推

表示状态

首先构思一下我们需要存储的信息,以此来确定 dp 数组的维数:

  • 下标
  • 最大和,即当前状态值

因为只有两项信息需要存储,所以可以使用一维数组。

我们用 \(dp[i]\) 表示表示以 \(nums[i]\) 结尾的连续子数组的最大和。

找状态转移方程

这里直接给出状态转移方程,因为我也不知道该怎么解释

\[dp[i] = \left\{ \begin{aligned} & nums[i] + dp[i - 1], & dp[i - 1] \geq 0, \\ & nums[i], & dp[i - 1] < 0. \end{aligned} \right. \]

边界处理

很容易知道 \(dp[0] = nums[0]\),并且 \(result = nums[0]\)

空间优化

因为 \(dp[i]\) 只和 \(dp[i-1]\) 有关,所以可以不断更新维护单变量 sum 求出最终结果。

代码

dp数组版

class Solution {
    public int maxSubArray(int[] nums) {
        int[] dp = new int[nums.length];
        int result = nums[0];

        dp[0] = nums[0];
        for(int i = 1; i < nums.length; i++){
            if(dp[i - 1] < 0){
                dp[i] = nums[i];
            }else{
                dp[i] = nums[i] + dp[i - 1];
            }

            result = Math.max(result, dp[i]);
        }

        return result;
    }
}

空间优化版

class Solution {
    public int maxSubArray(int[] nums) {
        int result = nums[0];
        int sum = nums[0];

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

            result = Math.max(result, sum);
        }

        return result;
    }
}
posted @ 2023-04-14 09:06  Frodo1124  阅读(43)  评论(0编辑  收藏  举报