Skip to content

Commit 1c4ab01

Browse files
Update
1 parent 64a885d commit 1c4ab01

11 files changed

+284
-49
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@
137137
* [回溯算法:电话号码的字母组合](https://mp.weixin.qq.com/s/e2ua2cmkE_vpYjM3j6HY0A)
138138
* [本周小结!(回溯算法系列一)](https://mp.weixin.qq.com/s/m2GnTJdkYhAamustbb6lmw)
139139
* [回溯算法:求组合总和(二)](https://mp.weixin.qq.com/s/FLg8G6EjVcxBjwCbzpACPw)
140+
* [回溯算法:求组合总和(三)](https://mp.weixin.qq.com/s/_1zPYk70NvHsdY8UWVGXmQ)
140141

141142
(持续更新中....)
142143

@@ -405,6 +406,7 @@
405406
|[0841.钥匙和房间](https://github.com/youngyangyang04/leetcode/blob/master/problems/0841.钥匙和房间.md) |孤岛问题 |中等|**bfs** **dfs**|
406407
|[0844.比较含退格的字符串](https://github.com/youngyangyang04/leetcode/blob/master/problems/0844.比较含退格的字符串.md) |字符串 |简单|**** **双指针优化** 使用栈的思路但没有必要使用栈|
407408
|[0925.长按键入](https://github.com/youngyangyang04/leetcode/blob/master/problems/0925.长按键入.md) |字符串 |简单|**双指针/模拟** 是一道模拟类型的题目|
409+
|[0941.有效的山脉数组](https://github.com/youngyangyang04/leetcode/blob/master/problems/0941.有效的山脉数组.md) |数组 |简单|**双指针**|
408410
|[0968.监控二叉树](https://github.com/youngyangyang04/leetcode/blob/master/problems/0968.监控二叉树.md) |二叉树 |困难|**贪心** 贪心与二叉树的结合|
409411
|[0977.有序数组的平方](https://github.com/youngyangyang04/leetcode/blob/master/problems/0977.有序数组的平方.md) |数组 |中等|**双指针** 还是比较巧妙的|
410412
|[1002.查找常用字符](https://github.com/youngyangyang04/leetcode/blob/master/problems/1002.查找常用字符.md) ||简单|****|

pics/131.分割回文串.png

10.2 KB
Loading

pics/57.插入区间.png

29.5 KB
Loading

pics/57.插入区间1.png

25.5 KB
Loading

pics/941.有效的山脉数组.png

61.5 KB
Loading

problems/0053.最大子序和.md

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
## 题目地址
33
https://leetcode-cn.com/problems/maximum-subarray/
44

5+
# 思路
6+
57
## 暴力解法
68

79
暴力解法的思路,第一层for 就是设置起始位置,第二层for循环遍历数组寻找最大值
@@ -27,12 +29,30 @@ public:
2729
```
2830

2931
## 贪心解法
32+
3033
贪心解法,其实不是很好理解, 看上面暴力的解法是两层for循环,那如何省掉一层for循环呢
31-
32-
其实**暴力解法中设置起始位置这个for循环是可以省略掉的**,这也是关键的一步,有了这个思路之后,就可以看一下代码了
3334

34-
时间复杂度:O(n)
35-
空间复杂度:O(1)
35+
**贪心贪的是哪里呢?**
36+
37+
如果 -2 1 在一起,计算起点的时候,一定是从1开始计算,因为负数只会拉低总和,这就是贪心贪的地方!
38+
39+
同样的道理,遍历nums,从头开始用count累积,如果count一旦加上nums[i]变为负数,那么就应该从nums[i+1]开始从头累积count了(也就是此时count要归0),因为已经变为负数的count,只会拖累总和。
40+
41+
相当于是不断调整区间的起始位置。
42+
43+
44+
**那有同学问了,区间终止位置不用调整么? 如何才能得到最大子序和呢?**
45+
46+
区间的终止位置,其实就是如果count取到最大值了,用result记录一下就可以了。
47+
48+
如动画所示:
49+
50+
<img src='../video/53.最大子序和.gif' width=600> </img></div>
51+
52+
红色的其实位置就是贪心每次取count为正数的时候,开始一个区间的统计。
53+
54+
不难写出如下C++代码(关键地方已经注释)
55+
3656
```
3757
class Solution {
3858
public:
@@ -41,14 +61,18 @@ public:
4161
int count = 0;
4262
for (int i = 0; i < nums.size(); i++) {
4363
count += nums[i];
44-
if (count > result) { // 相当于每次取各个终点的最大值
64+
if (count > result) { // 取区间累计的最大值(相当于不断确定最大子序终止位置)
4565
result = count;
4666
}
47-
if (count <= 0) count = 0; // 相当于重置起点,因为遇到负数一定是拉低总体数值的
67+
if (count <= 0) count = 0; // 相当于重置最大子序起始位置,因为遇到负数一定是拉低总和
4868
}
4969
return result;
5070
}
5171
};
5272
```
53-
> 更多算法干货文章持续更新,可以微信搜索「代码随想录」第一时间围观,关注后,回复「Java」「C++」 「python」「简历模板」「数据结构与算法」等等,就可以获得我多年整理的学习资料。
73+
时间复杂度:O(n)
74+
空间复杂度:O(1)
75+
76+
> 我是[程序员Carl](https://github.com/youngyangyang04),组队刷题可以找我,本文[leetcode刷题攻略](https://github.com/youngyangyang04/leetcode-master)已收录,更多[精彩算法文章](https://mp.weixin.qq.com/mp/appmsgalbum?__biz=MzUxNjY5NTYxNA==&action=getalbum&album_id=1485825793120387074&scene=173#wechat_redirect)尽在:[代码随想录](https://img-blog.csdnimg.cn/20200815195519696.png),期待你的关注!
77+
5478

problems/0057.插入区间.md

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
2+
这道题目合并的情况有很多种,想想都让人头疼。
3+
4+
我把这道题目化为三步:
5+
6+
## 步骤一:找到需要合并的区间
7+
8+
找到插入区间需要插入或者合并的位置。
9+
10+
代码如下:
11+
12+
```
13+
int index = 0; // intervals的索引
14+
while (index < intervals.size() && intervals[index][1] < newInterval[0]) {
15+
result.push_back(intervals[index++]);
16+
}
17+
```
18+
19+
此时intervals[index]就需要合并的区间了
20+
21+
## 步骤二:合并区间
22+
23+
合并区间还有两种情况
24+
25+
1. intervals[index]需要合并,如图:
26+
27+
<img src='../pics/57.插入区间.png' width=600> </img></div>
28+
29+
对于这种情况,只要是intervals[index]起始位置 <= newInterval终止位置,就要一直合并下去。
30+
31+
代码如下:
32+
33+
```
34+
while (index < intervals.size() && intervals[index][0] <= newInterval[1]) { // 注意防止越界
35+
newInterval[0] = min(intervals[index][0], newInterval[0]);
36+
newInterval[1] = max(intervals[index][1], newInterval[1]);
37+
index++;
38+
}
39+
```
40+
合并之后,将newInterval放入result就可以了
41+
42+
2. intervals[index]不用合并,插入区间直接插入就行,如图:
43+
44+
<img src='../pics/57.插入区间1.png' width=600> </img></div>
45+
46+
对于这种情况,就直接把newInterval放入result就可以了
47+
48+
## 步骤三:处理合并区间之后的区间
49+
50+
合并之后,就应该把合并之后的区间,以此加入result中。
51+
52+
代码如下:
53+
54+
```
55+
while (index < intervals.size()) {
56+
result.push_back(intervals[index++]);
57+
}
58+
```
59+
60+
# 整体C++代码
61+
62+
```
63+
class Solution {
64+
public:
65+
vector<vector<int>> insert(vector<vector<int>>& intervals, vector<int>& newInterval) {
66+
vector<vector<int>> result;
67+
int index = 0; // intervals的索引
68+
// 步骤一:找到需要合并的区间
69+
while (index < intervals.size() && intervals[index][1] < newInterval[0]) {
70+
result.push_back(intervals[index++]);
71+
}
72+
// 步骤二:合并区间
73+
while (index < intervals.size() && intervals[index][0] <= newInterval[1]) {
74+
newInterval[0] = min(intervals[index][0], newInterval[0]);
75+
newInterval[1] = max(intervals[index][1], newInterval[1]);
76+
index++;
77+
}
78+
result.push_back(newInterval);
79+
// 步骤三:处理合并区间之后的区间
80+
while (index < intervals.size()) {
81+
result.push_back(intervals[index++]);
82+
}
83+
return result;
84+
}
85+
};
86+
```

0 commit comments

Comments
 (0)