【算法】动态规划之LeetCode 53.最大子数组和

目录

文章目录

  • **目录**
  • 前言
    • 1.题目描述
    • 2. 动态规划法
  • 文章末尾


前言

本文主要是leetcode题解析,如果有什么需要改进的地方还请大佬指出⛺️

作者简介:大家好,我是青衿
☁️博客首页:CSDN主页放风讲故事
每日一句:努力一点,优秀一点

【算法】动态规划之LeetCode 53.最大子数组和_第1张图片

1.题目描述

给你一个整数数组 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数组的定义及下标含义用ai代表nums[i], 用f(i)代表以第i个数结尾的「连续子数组的最大和」, 网上也有很多文章介绍了是如何一步步分析来获得定义的过程的, 但我感觉对于新手来说, 可能还是多见一些类似的题目, 获得大量的经验, 这样比较有效果吧, 毕竟想研究动态规划的理论基础还是挺有难度的.

动态规划最重要的思想就是**利用上一个状态, 对于本题而言就是: 到底要不要加上上一个状态f(i-1)的信息, 这完全取决于f(i-1)的正负情况, 这样我们就能得出了动态规划的递推公式: f(i)=max{f(i−1)+ai,ai}

得到了递推公式后就可以编写代码了, 代码中的一个技巧就是对于空间复杂度的优化. 当使用动态规划只需要一个数(并不需要整个dp数组)时, 我们就没必要将整个dp数组都保存下来, 我们只需用变量来记录下我们需要的某个量即可, 这个优化方法在动态规划中还是非常常用的方法, 具体的实现参考代码.

2. 动态规划法

思路(动态规划)   O(n)
状态表示:f[i]表示以nums[i]为结尾的最大连续子数组和。
状态计算:如何确定f[i]的值? 以nums[i]为结尾的连续子数组共分为两种情况:
只有nums[i]一个数,则f[i] = nums[i];
以nums[i]为结尾的多个数,则f[i] = f[i - 1] + nums[i]。
两种情况取最大值,因此状态转移方程为:f[i] = max(f[i - 1] + nums[i], nums[i])。
初始化:f[0] = nums[0]。
最后遍历每个位置的f[i],然后其中的最大值即可。
时间复杂度分析: 只遍历一次数组,O(n)
class Solution {
    public int maxSubArray(int[] nums) {
        int n = nums.length;
        if (n == 0) return 0;
        int[] dp = new int[n];
        // base case
        // 第一个元素前面没有子数组
        dp[0] = nums[0];
        // 状态转移方程
        for (int i = 1; i < n; i++) {
            dp[i] = Math.max(nums[i], nums[i] + dp[i - 1]);
        }
        // 得到 nums 的最大子数组
        int res = Integer.MIN_VALUE;
        for (int i = 0; i < n; i++) {
            res = Math.max(res, dp[i]);
        }
        return res;
    }
}  

文章末尾

在这里插入图片描述

你可能感兴趣的:(算法,动态规划,代理模式)