Skip to content

Commit 11feb33

Browse files
Update
1 parent b4d2f98 commit 11feb33

10 files changed

+133
-30
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@
132132
8. [计算机专业要不要读研!](https://mp.weixin.qq.com/s/c9v1L3IjqiXtkNH7sOMAdg)
133133
9. [秋招和提前批都越来越提前了....](https://mp.weixin.qq.com/s/SNFiRDx8CKyjhTPlys6ywQ)
134134
10. [你的简历里「专业技能」写的够专业么?](https://mp.weixin.qq.com/s/bp6y-e5FVN28H9qc8J9zrg)
135+
11. [对于秋招,实习生也有烦恼....](https://mp.weixin.qq.com/s/ka07IPryFnfmIjByFFcXDg)
135136

136137

137138
## 数组
@@ -398,6 +399,7 @@
398399

399400
1. [单调栈:每日温度](./problems/0739.每日温度.md)
400401
2. [单调栈:下一个更大元素I](./problems/0496.下一个更大元素I.md)
402+
3. [单调栈:下一个更大元素II](./problems/0503.下一个更大元素II.md)
401403

402404
## 图论
403405

problems/0098.验证二叉搜索树.md

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232

3333
可以递归中序遍历将二叉搜索树转变成一个数组,代码如下:
3434

35-
```
35+
```C++
3636
vector<int> vec;
3737
void traversal(TreeNode* root) {
3838
if (root == NULL) return;
@@ -44,7 +44,7 @@ void traversal(TreeNode* root) {
4444
4545
然后只要比较一下,这个数组是否是有序的,**注意二叉搜索树中不能有重复元素**。
4646
47-
```
47+
```C++
4848
traversal(root);
4949
for (int i = 1; i < vec.size(); i++) {
5050
// 注意要小于等于,搜索树里不能有相同元素
@@ -55,7 +55,7 @@ return true;
5555

5656
整体代码如下:
5757

58-
```
58+
```C++
5959
class Solution {
6060
private:
6161
vector<int> vec;
@@ -162,7 +162,8 @@ return left && right;
162162
```
163163
164164
整体代码如下:
165-
```
165+
166+
```C++
166167
class Solution {
167168
public:
168169
long long maxVal = LONG_MIN; // 因为后台测试数据中有int最小值
@@ -188,7 +189,7 @@ public:
188189

189190
代码如下:
190191

191-
```
192+
```C++
192193
class Solution {
193194
public:
194195
TreeNode* pre = NULL; // 用来记录前一个节点
@@ -213,7 +214,7 @@ public:
213214

214215
迭代法中序遍历稍加改动就可以了,代码如下:
215216

216-
```
217+
```C++
217218
class Solution {
218219
public:
219220
bool isValidBST(TreeNode* root) {

problems/0110.平衡二叉树.md

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535

3636
## 题外话
3737

38-
咋眼一看这道题目和[二叉树:看看这些树的最大深度](https://mp.weixin.qq.com/s/guKwV-gSNbA1CcbvkMtHBg)很像,其实有很大区别。
38+
咋眼一看这道题目和[104.二叉树的最大深度](https://mp.weixin.qq.com/s/guKwV-gSNbA1CcbvkMtHBg)很像,其实有很大区别。
3939

4040
这里强调一波概念:
4141

@@ -50,11 +50,11 @@
5050

5151
因为求深度可以从上到下去查 所以需要前序遍历(中左右),而高度只能从下到上去查,所以只能后序遍历(左右中)
5252

53-
有的同学一定疑惑,为什么[二叉树:看看这些树的最大深度](https://mp.weixin.qq.com/s/guKwV-gSNbA1CcbvkMtHBg)中求的是二叉树的最大深度,也用的是后序遍历。
53+
有的同学一定疑惑,为什么[104.二叉树的最大深度](https://mp.weixin.qq.com/s/guKwV-gSNbA1CcbvkMtHBg)中求的是二叉树的最大深度,也用的是后序遍历。
5454

5555
**那是因为代码的逻辑其实是求的根节点的高度,而根节点的高度就是这颗树的最大深度,所以才可以使用后序遍历。**
5656

57-
[二叉树:看看这些树的最大深度](https://mp.weixin.qq.com/s/guKwV-gSNbA1CcbvkMtHBg)中,如果真正求取二叉树的最大深度,代码应该写成如下:(前序遍历)
57+
[104.二叉树的最大深度](https://mp.weixin.qq.com/s/guKwV-gSNbA1CcbvkMtHBg)中,如果真正求取二叉树的最大深度,代码应该写成如下:(前序遍历)
5858

5959
```C++
6060
class Solution {
@@ -227,7 +227,7 @@ public:
227227
228228
### 迭代
229229
230-
在[二叉树:看看这些树的最大深度](https://mp.weixin.qq.com/s/guKwV-gSNbA1CcbvkMtHBg)中我们可以使用层序遍历来求深度,但是就不能直接用层序遍历来求高度了,这就体现出求高度和求深度的不同。
230+
在[104.二叉树的最大深度](https://mp.weixin.qq.com/s/guKwV-gSNbA1CcbvkMtHBg)中我们可以使用层序遍历来求深度,但是就不能直接用层序遍历来求高度了,这就体现出求高度和求深度的不同。
231231
232232
本题的迭代方式可以先定义一个函数,专门用来求高度。
233233
@@ -448,7 +448,6 @@ class Solution {
448448
/**
449449
* 优化迭代法,针对暴力迭代法的getHeight方法做优化,利用TreeNode.val来保存当前结点的高度,这样就不会有重复遍历
450450
* 获取高度算法时间复杂度可以降到O(1),总的时间复杂度降为O(n)。
451-
* <p>
452451
* 时间复杂度:O(n)
453452
*/
454453
public boolean isBalanced(TreeNode root) {
@@ -493,7 +492,6 @@ class Solution {
493492
return height;
494493
}
495494
}
496-
// LeetCode题解链接:https://leetcode-cn.com/problems/balanced-binary-tree/solution/110-ping-heng-er-cha-shu-di-gui-fa-bao-l-yqr3/
497495
```
498496

499497
Python:
@@ -590,6 +588,7 @@ func abs(a int)int{
590588
return a
591589
}
592590
```
591+
593592
JavaScript:
594593
```javascript
595594
var isBalanced = function(root) {

problems/0337.打家劫舍III.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ return {val2, val1};
173173
174174
以示例1为例,dp数组状态如下:(**注意用后序遍历的方式推导**)
175175
176-
![337.打家劫舍III](https://img-blog.csdnimg.cn/20210129181331613.jpg)
176+
![337.打家劫舍III](https://code-thinking.cdn.bcebos.com/pics/337.打家劫舍III.jpg)
177177
178178
**最后头结点就是 取下标0 和 下标1的最大值就是偷得的最大金钱**。
179179

problems/0347.前K个高频元素.md

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,18 @@ https://leetcode-cn.com/problems/top-k-frequent-elements/
1818
给定一个非空的整数数组,返回其中出现频率前 k 高的元素。
1919

2020
示例 1:
21-
输入: nums = [1,1,1,2,2,3], k = 2
22-
输出: [1,2]
21+
* 输入: nums = [1,1,1,2,2,3], k = 2
22+
* 输出: [1,2]
2323

2424
示例 2:
25-
输入: nums = [1], k = 1
26-
输出: [1]
25+
* 输入: nums = [1], k = 1
26+
* 输出: [1]
2727

2828
提示:
29-
你可以假设给定的 k 总是合理的,且 1 ≤ k ≤ 数组中不相同的元素的个数。
30-
你的算法的时间复杂度必须优于 O(n log n) , n 是数组的大小。
31-
题目数据保证答案唯一,换句话说,数组中前 k 个高频元素的集合是唯一的。
32-
你可以按任意顺序返回答案。
29+
* 你可以假设给定的 k 总是合理的,且 1 ≤ k ≤ 数组中不相同的元素的个数。
30+
* 你的算法的时间复杂度必须优于 O(n log n) , n 是数组的大小。
31+
* 题目数据保证答案唯一,换句话说,数组中前 k 个高频元素的集合是唯一的。
32+
* 你可以按任意顺序返回答案。
3333

3434
# 思路
3535

@@ -70,7 +70,7 @@ https://leetcode-cn.com/problems/top-k-frequent-elements/
7070

7171
寻找前k个最大元素流程如图所示:(图中的频率只有三个,所以正好构成一个大小为3的小顶堆,如果频率更多一些,则用这个小顶堆进行扫描)
7272

73-
![347.前K个高频元素](https://code-thinking.cdn.bcebos.com/pics/347.%E5%89%8DK%E4%B8%AA%E9%AB%98%E9%A2%91%E5%85%83%E7%B4%A0.jpg)
73+
![347.前K个高频元素](https://code-thinking.cdn.bcebos.com/pics/347.前K个高频元素.jpg)
7474

7575

7676
我们来看一下C++代码:
@@ -126,10 +126,7 @@ public:
126126
优先级队列的定义正好反过来了,可能和优先级队列的源码实现有关(我没有仔细研究),我估计是底层实现上优先队列队首指向后面,队尾指向最前面的缘故!
127127
128128
129-
130-
131-
132-
## 其他语言版本
129+
# 其他语言版本
133130
134131
135132
Java:
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
2+
# 503.下一个更大元素II
3+
4+
链接:https://leetcode-cn.com/problems/next-greater-element-ii/
5+
6+
给定一个循环数组(最后一个元素的下一个元素是数组的第一个元素),输出每个元素的下一个更大元素。数字 x 的下一个更大的元素是按数组遍历顺序,这个数字之后的第一个比它更大的数,这意味着你应该循环地搜索它的下一个更大的数。如果不存在,则输出 -1。
7+
8+
示例 1:
9+
10+
* 输入: [1,2,1]
11+
* 输出: [2,-1,2]
12+
* 解释: 第一个 1 的下一个更大的数是 2;数字 2 找不到下一个更大的数;第二个 1 的下一个最大的数需要循环搜索,结果也是 2。
13+
14+
15+
# 思路
16+
17+
做本题之前建议先做[739. 每日温度](https://mp.weixin.qq.com/s/YeQ7eE0-hZpxJfJJziq25Q)[496.下一个更大元素 I](https://mp.weixin.qq.com/s/U0O6XkFOe-RMXthPS16sWQ)
18+
19+
这道题和[739. 每日温度](https://mp.weixin.qq.com/s/YeQ7eE0-hZpxJfJJziq25Q)也几乎如出一辙。
20+
21+
不同的时候本题要循环数组了。
22+
23+
关于单调栈的讲解我在题解[739. 每日温度](https://mp.weixin.qq.com/s/YeQ7eE0-hZpxJfJJziq25Q)中已经详细讲解了。
24+
25+
本篇我侧重与说一说,如何处理循环数组。
26+
27+
相信不少同学看到这道题,就想那我直接把两个数组拼接在一起,然后使用单调栈求下一个最大值不就行了!
28+
29+
确实可以!
30+
31+
讲两个nums数组拼接在一起,使用单调栈计算出每一个元素的下一个最大值,最后再把结果集即result数组resize到原数组大小就可以了。
32+
33+
代码如下:
34+
35+
```C++
36+
// 版本一
37+
class Solution {
38+
public:
39+
vector<int> nextGreaterElements(vector<int>& nums) {
40+
// 拼接一个新的nums
41+
vector<int> nums1(nums.begin(), nums.end());
42+
nums.insert(nums.end(), nums1.begin(), nums1.end());
43+
// 用新的nums大小来初始化result
44+
vector<int> result(nums.size(), -1);
45+
if (nums.size() == 0) return result;
46+
47+
// 开始单调栈
48+
stack<int> st;
49+
for (int i = 0; i < nums.size(); i++) {
50+
while (!st.empty() && nums[i] > nums[st.top()]) {
51+
result[st.top()] = nums[i];
52+
st.pop();
53+
}
54+
st.push(i);
55+
}
56+
// 最后再把结果集即result数组resize到原数组大小
57+
result.resize(nums.size() / 2);
58+
return result;
59+
}
60+
};
61+
62+
```
63+
64+
这种写法确实比较直观,但做了很多无用操作,例如修改了nums数组,而且最后还要把result数组resize回去。
65+
66+
resize倒是不费时间,是O(1)的操作,但扩充nums数组相当于多了一个O(n)的操作。
67+
68+
其实也可以不扩充nums,而是在遍历的过程中模拟走了两边nums。
69+
70+
代码如下:
71+
72+
```C++
73+
// 版本二
74+
class Solution {
75+
public:
76+
vector<int> nextGreaterElements(vector<int>& nums) {
77+
vector<int> result(nums.size(), -1);
78+
if (nums.size() == 0) return result;
79+
stack<int> st;
80+
for (int i = 0; i < nums.size() * 2; i++) {
81+
// 模拟遍历两边nums,注意一下都是用i % nums.size()来操作
82+
while (!st.empty() && nums[i % nums.size()] > nums[st.top()]) {
83+
result[st.top()] = nums[i % nums.size()];
84+
st.pop();
85+
}
86+
st.push(i % nums.size());
87+
}
88+
return result;
89+
}
90+
};
91+
```
92+
93+
可以版本二不仅代码精简了,也比版本一少做了无用功!
94+
95+
## 其他语言版本
96+
97+
Java:
98+
99+
Python:
100+
101+
Go:
102+
103+
JavaScript:

problems/0513.找树左下角的值.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737

3838
如果使用递归法,如何判断是最后一行呢,其实就是深度最大的叶子节点一定是最后一行。
3939

40-
如果对二叉树深度和高度还有点疑惑的话,请看:[二叉树:我平衡么?](https://mp.weixin.qq.com/s/isUS-0HDYknmC0Rr4R8mww)
40+
如果对二叉树深度和高度还有点疑惑的话,请看:[110.平衡二叉树](https://mp.weixin.qq.com/s/isUS-0HDYknmC0Rr4R8mww)
4141

4242
所以要找深度最大的叶子节点。
4343

@@ -207,7 +207,7 @@ public:
207207
208208
本题涉及如下几点:
209209
210-
* 递归求深度的写法,我们在[二叉树:我平衡么?](https://mp.weixin.qq.com/s/isUS-0HDYknmC0Rr4R8mww)中详细的分析了深度应该怎么求,高度应该怎么求。
210+
* 递归求深度的写法,我们在[110.平衡二叉树](https://mp.weixin.qq.com/s/isUS-0HDYknmC0Rr4R8mww)中详细的分析了深度应该怎么求,高度应该怎么求。
211211
* 递归中其实隐藏了回溯,在[二叉树:以为使用了递归,其实还隐藏着回溯](https://mp.weixin.qq.com/s/ivLkHzWdhjQQD1rQWe6zWA)中讲解了究竟哪里使用了回溯,哪里隐藏了回溯。
212212
* 层次遍历,在[二叉树:层序遍历登场!](https://mp.weixin.qq.com/s/Gb3BjakIKGNpup2jYtTzog)深度讲解了二叉树层次遍历。
213213
所以本题涉及到的点,我们之前都讲解过,这些知识点需要同学们灵活运用,这样就举一反三了。

problems/二叉树理论基础.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
<a href="https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ"><img src="https://img.shields.io/badge/知识星球-代码随想录-blue" alt=""></a>
66
</p>
77
<p align="center"><strong>欢迎大家<a href="https://mp.weixin.qq.com/s/tqCxrMEU-ajQumL1i8im9A">参与本项目</a>,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!</strong></p>
8+
89
# 二叉树理论基础篇
910

1011
我们要开启新的征程了,大家跟上!

problems/二叉树的递归遍历.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ void traversal(TreeNode* cur, vector<int>& vec) {
111111
112112
113113
114-
## 其他语言版本
114+
# 其他语言版本
115115
116116
117117
Java:

problems/背包理论基础01背包-1.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ dp[0][j] 和 dp[i][0] 都已经初始化了,那么其他下标应该初始化
125125

126126
其实从递归公式: dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]); 可以看出dp[i][j] 是又左上方数值推导出来了,那么 其他下标初始为什么数值都可以,因为都会被覆盖。
127127

128-
初始-1,初始-2,初始100,都可以!
128+
**初始-1,初始-2,初始100,都可以!**
129129

130130
但只不过一开始就统一把dp数组统一初始为0,更方便一些。
131131

0 commit comments

Comments
 (0)