docs: 最大子序列和添加视频讲解链接

This commit is contained in:
liangzhensheng
2023-03-17 11:14:43 +08:00
parent 5678f566a8
commit ef8500d4cf

View File

@ -4,7 +4,6 @@
</a>
<p align="center"><strong><a href="https://mp.weixin.qq.com/s/tqCxrMEU-ajQumL1i8im9A">参与本项目</a>,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!</strong></p>
# 53. 最大子序和
[力扣题目链接](https://leetcode.cn/problems/maximum-subarray/)
@ -12,17 +11,21 @@
给定一个整数数组 nums 找到一个具有最大和的连续子数组子数组最少包含一个元素返回其最大和。
示例:
* 输入: [-2,1,-3,4,-1,2,1,-5,4]
* 输出: 6
* 解释: 连续子数组 [4,-1,2,1] 的和最大 6。
- 输入: [-2,1,-3,4,-1,2,1,-5,4]
- 输出: 6
- 解释:  连续子数组  [4,-1,2,1] 的和最大,为  6。
# 视频讲解
**《代码随想录》算法视频公开课:[贪心算法的巧妙需要慢慢体会LeetCode53. 最大子序和](https://www.bilibili.com/video/BV1aY4y1Z7ya),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
## 暴力解法
暴力解法的思路第一层for 就是设置起始位置第二层for循环遍历数组寻找最大值
暴力解法的思路,第一层 for 就是设置起始位置,第二层 for 循环遍历数组寻找最大值
* 时间复杂度O(n^2)
* 空间复杂度O(1)
- 时间复杂度O(n^2)
- 空间复杂度O(1)
```CPP
class Solution {
@ -42,13 +45,13 @@ public:
};
```
以上暴力的解法C++勉强可以过,其他语言就不确定了。
以上暴力的解法 C++勉强可以过,其他语言就不确定了。
## 贪心解法
**贪心贪的是哪里呢?**
如果 -2 1 在一起,计算起点的时候,一定是从1开始计算,因为负数只会拉低总和,这就是贪心贪的地方!
如果 -2 1 在一起,计算起点的时候,一定是从 1 开始计算,因为负数只会拉低总和,这就是贪心贪的地方!
局部最优:当前“连续和”为负数的时候立刻放弃,从下一个元素重新计算“连续和”,因为负数加上下一个元素 “连续和”只会越来越小。
@ -56,29 +59,27 @@ public:
**局部最优的情况下,并记录最大的“连续和”,可以推出全局最优**
从代码角度上来讲遍历nums从头开始用count累积如果count一旦加上nums[i]变为负数那么就应该从nums[i+1]开始从0累积count了因为已经变为负数的count只会拖累总和。
从代码角度上来讲:遍历 nums从头开始用 count 累积,如果 count 一旦加上 nums[i]变为负数,那么就应该从 nums[i+1]开始从 0 累积 count 了,因为已经变为负数的 count只会拖累总和。
**这相当于是暴力解法中的不断调整最大子序和区间的起始位置**
**那有同学问了,区间终止位置不用调整么? 如何才能得到最大“连续和”呢?**
区间的终止位置其实就是如果count取到最大值了及时记录下来了。例如如下代码
区间的终止位置,其实就是如果 count 取到最大值了,及时记录下来了。例如如下代码:
```
if (count > result) result = count;
```
**这样相当于是用result记录最大子序和区间和变相的算是调整了终止位置**
**这样相当于是用 result 记录最大子序和区间和(变相的算是调整了终止位置)**
如动画所示:
![53.最大子序和](https://code-thinking.cdn.bcebos.com/gifs/53.%E6%9C%80%E5%A4%A7%E5%AD%90%E5%BA%8F%E5%92%8C.gif)
红色的起始位置就是贪心每次取count为正数的时候开始一个区间的统计。
红色的起始位置就是贪心每次取 count 为正数的时候,开始一个区间的统计。
那么不难写出如下C++代码(关键地方已经注释)
那么不难写出如下 C++代码(关键地方已经注释)
```CPP
class Solution {
@ -98,18 +99,16 @@ public:
};
```
* 时间复杂度O(n)
* 空间复杂度O(1)
- 时间复杂度O(n)
- 空间复杂度O(1)
当然题目没有说如果数组为空,应该返回什么,所以数组为空的话返回啥都可以了。
## 常见误区
误区一:
不少同学认为 如果输入用例都是-1或者 都是负数这个贪心算法跑出来的结果是0 这是**又一次证明脑洞模拟不靠谱的经典案例**,建议大家把代码运行一下试一试,就知道了,也会理解 为什么 result 要初始化为最小负数了。
不少同学认为 如果输入用例都是-1或者 都是负数,这个贪心算法跑出来的结果是 0 这是**又一次证明脑洞模拟不靠谱的经典案例**,建议大家把代码运行一下试一试,就知道了,也会理解 为什么 result 要初始化为最小负数了。
误区二:
@ -117,19 +116,17 @@ public:
在动画演示用,大家可以发现, 4遇到 -1 的时候,我们依然累加了,为什么呢?
因为和为3只要连续和还是正数就会 对后面的元素 起到增大总和的作用。 所以只要连续和为正数我们就保留。
因为和为 3只要连续和还是正数就会 对后面的元素 起到增大总和的作用。 所以只要连续和为正数我们就保留。
这里也会有录友疑惑,那 4 + -1 之后 不就变小了吗? 会不会错过 4 成为最大连续和的可能性?
其实并不会因为还有一个变量result 一直在更新 最大的连续和只要有更大的连续和出现result就更新了那么result已经把4更新了,后面 连续和变成3也不会对最后结果有影响。
其实并不会,因为还有一个变量 result 一直在更新 最大的连续和只要有更大的连续和出现result 就更新了,那么 result 已经把 4 更新了,后面 连续和变成 3也不会对最后结果有影响。
## 动态规划
当然本题还可以用动态规划来做,当前[「代码随想录」](https://img-blog.csdnimg.cn/20201124161234338.png)主要讲解贪心系列后续到动态规划系列的时候会详细讲解本题的dp方法。
当然本题还可以用动态规划来做,当前[「代码随想录」](https://img-blog.csdnimg.cn/20201124161234338.png)主要讲解贪心系列,后续到动态规划系列的时候会详细讲解本题的 dp 方法。
那么先给出我的dp代码如下有时间的录友可以提前做一做
那么先给出我的 dp 代码如下,有时间的录友可以提前做一做:
```CPP
class Solution {
@ -148,8 +145,8 @@ public:
};
```
* 时间复杂度O(n)
* 空间复杂度O(n)
- 时间复杂度O(n)
- 空间复杂度O(n)
## 总结
@ -159,8 +156,8 @@ public:
## 其他语言版本
### Java
```java
class Solution {
public int maxSubArray(int[] nums) {
@ -201,6 +198,7 @@ class Solution {
```
### Python
```python
class Solution:
def maxSubArray(self, nums: List[int]) -> int:
@ -233,6 +231,7 @@ func maxSubArray(nums []int) int {
```
### Rust
```rust
pub fn max_sub_array(nums: Vec<i32>) -> i32 {
let mut max_sum = i32::MIN;
@ -247,6 +246,7 @@ pub fn max_sub_array(nums: Vec<i32>) -> i32 {
```
### Javascript:
```Javascript
var maxSubArray = function(nums) {
let result = -Infinity
@ -264,9 +264,10 @@ var maxSubArray = function(nums) {
};
```
### C:
贪心:
```c
int maxSubArray(int* nums, int numsSize){
int maxVal = INT_MIN;
@ -286,6 +287,7 @@ int maxSubArray(int* nums, int numsSize){
```
动态规划:
```c
/**
* 解题思路:动态规划:
@ -332,7 +334,7 @@ function maxSubArray(nums: number[]): number {
if (curSum < 0) curSum = 0;
}
return resMax;
};
}
```
**动态规划**
@ -350,7 +352,7 @@ function maxSubArray(nums: number[]): number {
resMax = Math.max(resMax, dp[i]);
}
return resMax;
};
}
```
### Scala