Skip to content

Commit b4bca71

Browse files
Update
1 parent 25772fa commit b4bca71

File tree

3 files changed

+101
-8
lines changed

3 files changed

+101
-8
lines changed

README.md

Lines changed: 56 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -74,17 +74,52 @@
7474

7575
* 二叉树经典题目
7676

77-
78-
(待补充.....)
77+
(补充ing)
7978

8079
# 算法模板
8180

82-
## 二分法
83-
(待补充....)
81+
## 二分查找法
82+
83+
```
84+
class Solution {
85+
public:
86+
int searchInsert(vector<int>& nums, int target) {
87+
int n = nums.size();
88+
int left = 0;
89+
int right = n; // 我们定义target在左闭右开的区间里,[left, right)
90+
while (left < right) { // 因为left == right的时候,在[left, right)是无效的空间
91+
int middle = left + ((right - left) >> 1);
92+
if (nums[middle] > target) {
93+
right = middle; // target 在左区间,因为是左闭右开的区间,nums[middle]一定不是我们的目标值,所以right = middle,在[left, middle)中继续寻找目标值
94+
} else if (nums[middle] < target) {
95+
left = middle + 1; // target 在右区间,在 [middle+1, right)中
96+
} else { // nums[middle] == target
97+
return middle; // 数组中找到目标值的情况,直接返回下标
98+
}
99+
}
100+
return right;
101+
}
102+
};
103+
104+
```
84105

85106
## KMP
86107

87-
(待补充....)
108+
```
109+
void kmp(int* next, const string& s){
110+
next[0] = -1;
111+
int j = -1;
112+
for(int i = 1; i < s.size(); i++){
113+
while (j >= 0 && s[i] != s[j + 1]) {
114+
j = next[j];
115+
}
116+
if (s[i] == s[j + 1]) {
117+
j++;
118+
}
119+
next[i] = j;
120+
}
121+
}
122+
```
88123

89124
## 二叉树
90125

@@ -226,8 +261,24 @@ vector<vector<int>> levelOrder(TreeNode* root) {
226261

227262
### 二叉树深度
228263

264+
```
265+
int getDepth(TreeNode* node) {
266+
if (node == NULL) return 0;
267+
return 1 + max(getDepth(node->left), getDepth(node->right));
268+
}
269+
```
270+
(补充ing)
271+
229272
### 二叉树节点数量
230273

274+
```
275+
int countNodes(TreeNode* root) {
276+
if (root == NULL) return 0;
277+
return 1 + countNodes(root->left) + countNodes(root->right);
278+
}
279+
```
280+
281+
231282
# LeetCode 最强题解:
232283

233284
|题目 | 类型 | 难度 | 解题方法 |

problems/0144.二叉树的前序遍历.md

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -177,9 +177,7 @@ public:
177177
178178
```
179179

180-
那么后序遍历呢
181-
182-
先序遍历是中左右,后续遍历是左右中,那么我们只需要调整一下先序遍历的代码顺序,就变成中右左的遍历顺序
180+
再来看后序遍历,先序遍历是中左右,后续遍历是左右中,那么我们只需要调整一下先序遍历的代码顺序,就变成中右左的遍历顺序
183181
,然后在反转result数组,输出的结果顺序就是左右中了,如下图:
184182
![前序到后序](https://img-blog.csdnimg.cn/20200808200338924.png)
185183

@@ -208,8 +206,52 @@ public:
208206
209207
```
210208

209+
此时我们实现了前后中遍历的三种迭代法,是不是发现迭代法实现的先中后序,其实风格也不是那么统一,除了先序和后序,有关联,中序完全就是另一个风格了,一会用栈遍历,一会又用指针来遍历。
210+
211+
重头戏来了,接下来介绍一下统一写法。
212+
213+
#### 迭代法统一写法
214+
215+
我们以中序遍历为例,之前说使用栈的话,**无法同时解决处理过程和访问过程不一致的情况**,那我们就将访问的节点放入栈中,把要处理的节点也放入栈中但是要做标记,标记就是要处理的节点放入栈之后,紧接着放入一个空指针作为标记。
216+
217+
代码如下:
218+
```
219+
class Solution {
220+
public:
221+
vector<int> inorderTraversal(TreeNode* root) {
222+
vector<int> result;
223+
stack<TreeNode*> st;
224+
if (root != NULL) st.push(root);
225+
while (!st.empty()) {
226+
TreeNode* node = st.top();
227+
if (node != NULL) {
228+
st.pop(); // 将该节点弹出,避免重复操作,下面再将右中左节点添加到栈中
229+
if (node->right) st.push(node->right); // 添加右节点
230+
231+
st.push(node); // 添加中节点
232+
st.push(NULL); // 中节点访问过,但是还没有处理,需要做一下标记。
233+
234+
if (node->left) st.push(node->left); // 添加左节点
235+
} else {
236+
st.pop(); // 将空节点弹出
237+
node = st.top(); // 重新取出栈中元素
238+
st.pop();
239+
result.push_back(node->val); // 加入到数组中
240+
}
241+
}
242+
return result;
243+
}
244+
};
245+
```
246+
247+
看代码有点抽象我们来看一下动画:
248+
249+
<video src='../video/中序遍历迭代(统一写法).mp4' controls='controls' width='640' height='320' autoplay='autoplay'> Your browser does not support the video tag.</video></div>
250+
211251

252+
大家在看一下具体代码实现
212253

254+
接下来给大家介绍一种统一的写法。
213255

214256
我们再来看一下代码。
215257
## C++代码
2.52 MB
Binary file not shown.

0 commit comments

Comments
 (0)