⭐算法入门⭐《动态规划 - 线性DP》简单02 —— LeetCode 53. 最大子序和
Posted 英雄哪里出来
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了⭐算法入门⭐《动态规划 - 线性DP》简单02 —— LeetCode 53. 最大子序和相关的知识,希望对你有一定的参考价值。
🙉饭不食,水不饮,题必须刷🙉
还不会C语言,和我一起打卡! 🌞《光天化日学C语言》🌞
LeetCode 太难?上简单题! 🧡《C语言入门100例》🧡
LeetCode 太简单?大神盘他! 🌌《夜深人静写算法》🌌
一、题目
1、题目描述
给定一个整数数组 n u m s nums nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
样例输入: n u m s = [ − 2 , 1 , − 3 , 4 , − 1 , 2 , 1 , − 5 , − 7 ] nums = [-2,1,-3,4,-1,2,1,-5,-7] nums=[−2,1,−3,4,−1,2,1,−5,−7]
样例输出: 6 6 6, 即 [ 4 , − 1 , 2 , 1 ] [4,-1,2,1] [4,−1,2,1]。
2、基础框架
- c++ 版本给出的基础框架代码如下:
class Solution {
public:
int maxSubArray(vector<int>& nums) {
}
};
3、原题链接
二、解题报告
1、思路分析
由于要求的是连续的子数组,所以对于第 i i i 个元素,状态转移一定是从 i − 1 i-1 i−1 个元素转移过来的。
- 基于这一点,可以令 f [ i ] f[i] f[i] 表示以 i i i 号元素结尾的最大值。
- 那么很自然,这个最大值必然包含 n u m s [ i ] nums[i] nums[i] 这个元素,那么要不要包含 n u m s [ i − 1 ] , n u m s [ i − 2 ] , n u m s [ i − 3 ] , . . . , n u m s [ k ] nums[i-1],nums[i-2],nums[i-3],...,nums[k] nums[i−1],nums[i−2],nums[i−3],...,nums[k] 呢?其实就是看第 i − 1 i-1 i−1 号元素结尾的最大值是否大于零,也就是:当 f [ i − 1 ] ≤ 0 f[i-1] \\le 0 f[i−1]≤0 时,则 前 i − 1 i-1 i−1 个元素是没必要包含进来的。所以就有状态转移方程:
- f [ i ] = { n u m s [ 0 ] i = 0 n u m s [ i ] f [ i − 1 ] ≤ 0 n u m s [ i ] + f [ i − 1 ] f [ i − 1 ] > 0 f[i] = \\begin{cases} nums[0] & i = 0 \\\\ nums[i] & f[i-1] \\le 0 \\\\ nums[i] + f[i-1] & f[i-1] > 0\\end{cases} f[i]=⎩⎪⎨⎪⎧nums[0]nums[i]nums[i]+f[i−1]i=0f[i−1]≤0f[i−1]>0
- 一层循环枚举后,取 m a x ( f [ i ] ) max(f[i]) max(f[i]) 就是答案了。
2、时间复杂度
- 状态数: O ( n ) O(n) O(n)
- 状态转移: O ( 1 ) O(1) O(1)
- 时间复杂度: O ( n ) O(n) O(n)
3、代码详解
class Solution {
int f[30010];
public:
int maxSubArray(vector<int>& nums) {
int maxValue = nums[0];
f[0] = nums[0]; // (1)
for(int i = 1; i < nums.size(); ++i) {
f[i] = nums[i];
if(f[i-1] > 0) {
f[i] += f[i-1]; // (2)
}
maxValue = max(maxValue, f[i]); // (3)
}
return maxValue;
}
};
- ( 1 ) (1) (1) 初始值;
- ( 2 ) (2) (2) 状态转移;
- ( 3 ) (3) (3) 过程中取最大值;
三、本题小知识
连续子数组问题,可以考虑前一个元素已经计算出来的状态进行下一个元素的求解。
以上是关于⭐算法入门⭐《动态规划 - 线性DP》简单02 —— LeetCode 53. 最大子序和的主要内容,如果未能解决你的问题,请参考以下文章
⭐算法入门⭐《动态规划 - 线性DP》中等01 —— LeetCode 198. 打家劫舍