mirror of
https://github.com/youngyangyang04/leetcode-master.git
synced 2025-07-06 15:09:40 +08:00
Update
This commit is contained in:
@ -309,6 +309,7 @@
|
||||
|[0501.二叉搜索树中的众数](https://github.com/youngyangyang04/leetcode/blob/master/problems/0501.二叉搜索树中的众数.md) |二叉树 |简单|**递归/中序遍历**|
|
||||
|[0513.找树左下角的值](https://github.com/youngyangyang04/leetcode/blob/master/problems/0513.找树左下角的值.md) |二叉树 |中等|**递归** **迭代**|
|
||||
|[0515.在每个树行中找最大值](https://github.com/youngyangyang04/leetcode/blob/master/problems/0515.在每个树行中找最大值.md) |二叉树 |简单|**广度优先搜索/队列**|
|
||||
|[0530.二叉搜索树的最小绝对差](https://github.com/youngyangyang04/leetcode/blob/master/problems/0530.二叉搜索树的最小绝对差.md) |二叉树搜索树 |简单|**递归** **迭代**|
|
||||
|[0538.把二叉搜索树转换为累加树](https://github.com/youngyangyang04/leetcode/blob/master/problems/0538.把二叉搜索树转换为累加树.md) |二叉树 |简单|**递归** **迭代**|
|
||||
|[0541.反转字符串II](https://github.com/youngyangyang04/leetcode/blob/master/problems/0541.反转字符串II.md) |字符串 |简单| **模拟**|
|
||||
|[0559.N叉树的最大深度](https://github.com/youngyangyang04/leetcode/blob/master/problems/0559.N叉树的最大深度.md) |N叉树 |简单| **递归**|
|
||||
@ -336,7 +337,7 @@
|
||||
|
||||
# 关于作者
|
||||
|
||||
大家好,我是程序员Carl,ACM 校赛、黑龙江省赛、东北四省赛金牌,和亚洲区域赛铜牌获得者,哈工大计算机硕士毕业,先后在腾讯和百度从事后端技术研发,CSDN博客专家。对算法和C++后端技术有一定的见解,利用工作之余重新刷leetcode。
|
||||
大家好,我是程序员Carl,哈工大师兄,ACM 校赛、黑龙江省赛、东北四省赛金牌、亚洲区域赛铜牌获得者,先后在腾讯和百度从事后端技术研发,CSDN博客专家。对算法和C++后端技术有一定的见解,利用工作之余重新刷leetcode。
|
||||
|
||||
**加我的微信,备注:「个人简单介绍」+「组队刷题」**, 拉你进刷题群,每天一道经典题目分析,而且题目不是孤立的,每一道题目之间都是有关系的,都是由浅入深一脉相承的,所以学习效果最好是每篇连续着看,也许之前你会某些知识点,但是一直没有把知识点串起来,这里每天一篇文章就会帮你把知识点串起来。我也花了不少精力来整理我的题解,**而且我不会在群里发任何广告,纯自己学习和分享。 欢迎你的加入!**
|
||||
|
||||
|
BIN
pics/700.二叉搜索树中的搜索.png
Normal file
BIN
pics/700.二叉搜索树中的搜索.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 32 KiB |
@ -36,22 +36,29 @@ KMP的经典思想就是:**当出现字符串不匹配时,可以记录一部
|
||||
|
||||
本篇将以如下顺序来讲解KMP,
|
||||
|
||||
1. 什么是KMP
|
||||
2. KMP可以解决什么问题
|
||||
3. 分析KMP算法里的next数组
|
||||
4. 什么是前缀表
|
||||
5. 再分析为什么要是前缀表而不是什么哈希表其他表等等,偏偏要是前缀表。
|
||||
6. 一步一步推导前缀表是怎么求的
|
||||
7. 时间复杂度分析
|
||||
8. 前缀表与next数组的关系
|
||||
9. 如何使用next数组来做一遍匹配的过程
|
||||
10. 构造next数组
|
||||
11. 使用next数组进行匹配
|
||||
12. 前缀表统一减一(右移)的KMP实现方式
|
||||
13. 前缀表不减一的KMP实现方式
|
||||
14. 总结
|
||||
|
||||
可以说步步相扣,大家要跟紧,哈哈。
|
||||
* 什么是KMP
|
||||
* KMP有什么用
|
||||
* 什么是前缀表
|
||||
* 为什么一定要用前缀表
|
||||
* 如何计算前缀表
|
||||
* 前缀表与next数组
|
||||
* 使用next数组来匹配
|
||||
* 时间复杂度分析
|
||||
* 构造next数组
|
||||
* 使用next数组来做匹配
|
||||
* 前缀表统一减一 C++代码实现
|
||||
* 前缀表(不减一)C++实现
|
||||
* 总结
|
||||
|
||||
|
||||
读完本篇可以顺便,把leetcode上28.实现strStr()题目做了。
|
||||
|
||||
如果文字实在看不下去,就看我在B站上的视频吧,如下:
|
||||
|
||||
* [帮你把KMP算法学个通透!(理论篇)B站](https://www.bilibili.com/video/BV1PD4y1o7nd/)
|
||||
* [帮你把KMP算法学个通透!(求next数组代码篇)B站](https://www.bilibili.com/video/BV1M5411j7Xx/)
|
||||
|
||||
|
||||
# 什么是KMP
|
||||
|
||||
@ -525,5 +532,7 @@ public:
|
||||
可以说把KMP的每一个细微的细节都扣了出来,毫无遮掩的展示给大家了!
|
||||
|
||||
|
||||
|
||||
|
||||
> 更多算法干货文章持续更新,可以微信搜索「代码随想录」第一时间围观,关注后,回复「Java」「C++」 「python」「简历模板」「数据结构与算法」等等,就可以获得我多年整理的学习资料。
|
||||
|
||||
|
@ -1,17 +1,35 @@
|
||||
## 题目地址
|
||||
https://leetcode-cn.com/problems/search-in-a-binary-search-tree/
|
||||
|
||||
## 思路
|
||||
> 二叉搜索树登场!
|
||||
|
||||
### 递归法
|
||||
# 700.二叉搜索树中的搜索
|
||||
|
||||
先来看递归的实现方式。
|
||||
给定二叉搜索树(BST)的根节点和一个值。 你需要在BST中找到节点值等于给定值的节点。 返回以该节点为根的子树。 如果节点不存在,则返回 NULL。
|
||||
|
||||
依然从递归三要素开始分析:
|
||||
例如,
|
||||
|
||||
* 确定递归函数的参数和返回值
|
||||
* 确定终止条件
|
||||
* 确定单层递归的逻辑
|
||||
<img src='../pics/700.二叉搜索树中的搜索.png' width=600> </img></div>
|
||||
|
||||
在上述示例中,如果要找的值是 5,但因为没有节点值为 5,我们应该返回 NULL。
|
||||
|
||||
# 思路
|
||||
|
||||
之前我们讲了都是普通二叉树,那么接下来看看二叉搜索树。
|
||||
|
||||
在[关于二叉树,你该了解这些!](https://mp.weixin.qq.com/s/_ymfWYvTNd2GvWvC5HOE4A)中,我们已经讲过了二叉搜索树。
|
||||
|
||||
二叉搜索树是一个有序树:
|
||||
|
||||
* 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
|
||||
* 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
|
||||
* 它的左、右子树也分别为二叉搜索树
|
||||
|
||||
这就决定了,二叉搜索树,递归遍历和迭代遍历和普通二叉树都不一样。
|
||||
|
||||
本题,其实就是在二叉搜索树中搜索一个节点。那么我们来看看应该如何遍历。
|
||||
|
||||
## 递归法
|
||||
|
||||
1. 确定递归函数的参数和返回值
|
||||
|
||||
@ -33,17 +51,25 @@ if (root == NULL || root->val == val) return root;
|
||||
|
||||
3. 确定单层递归的逻辑
|
||||
|
||||
来看一下二叉搜索树的单层递归逻辑有何不同, 因为二叉搜索树的节点是有序的,所以可以有方向的去搜索,如果root->val > val,搜索左子树,如果root->val < val,就搜索右子树,最后如果都没有搜索到,就返回NULL。
|
||||
看看二叉搜索树的单层递归逻辑有何不同。
|
||||
|
||||
因为二叉搜索树的节点是有序的,所以可以有方向的去搜索。
|
||||
|
||||
如果root->val > val,搜索左子树,如果root->val < val,就搜索右子树,最后如果都没有搜索到,就返回NULL。
|
||||
|
||||
代码如下:
|
||||
|
||||
```
|
||||
if (root->val > val) return searchBST(root->left, val);
|
||||
if (root->val > val) return searchBST(root->left, val); // 注意这里加了return
|
||||
if (root->val < val) return searchBST(root->right, val);
|
||||
return NULL;
|
||||
```
|
||||
|
||||
这里可能会疑惑,在递归遍历的时候,什么时候直接return 递归函数的返回值,什么时候不用加这个 return, 这取决于对递归函数的定义,这里定义的递归函数,就是返回 要查找的元素所在的节点,而这个节点就是我们所求,所以直接return递归函数的返回值。
|
||||
这里可能会疑惑,在递归遍历的时候,什么时候直接return 递归函数的返回值,什么时候不用加这个 return呢。
|
||||
|
||||
我们在[二叉树:递归函数究竟什么时候需要返回值,什么时候不要返回值?](https://mp.weixin.qq.com/s/6TWAVjxQ34kVqROWgcRFOg)中讲了,如果要搜索一条边,递归函数就要加返回值,这里也是一样的道理。
|
||||
|
||||
**因为搜索到目标节点了,就要立即return了,这样才是找到节点就返回(搜索某一条边),如果不加return,就是遍历整棵树了。**
|
||||
|
||||
整体代码如下:
|
||||
|
||||
@ -56,16 +82,23 @@ TreeNode* searchBST(TreeNode* root, int val) {
|
||||
}
|
||||
```
|
||||
|
||||
### 迭代法
|
||||
## 迭代法
|
||||
|
||||
一提到二叉树遍历的迭代法,可能立刻想起使用栈来模拟深度遍历,使用队列来模拟广度遍历,其实因为二叉搜索树的特殊性,也就是节点的有序性,可以不使用辅助栈或者队列就可以写出迭代法。
|
||||
一提到二叉树遍历的迭代法,可能立刻想起使用栈来模拟深度遍历,使用队列来模拟广度遍历。
|
||||
|
||||
对于一般二叉树,模拟递归的过程中还有一个回溯的过程,例如走一个左方向的分支走到头了,那么要调头,在走右分支。而对于二叉搜索树,不需要回溯的过程,因为节点的有序性就帮我们确定了搜索的方向。
|
||||
对于二叉搜索树可就不一样了,因为二叉搜索树的特殊性,也就是节点的有序性,可以不使用辅助栈或者队列就可以写出迭代法。
|
||||
|
||||
对于一般二叉树,递归过程中还有回溯的过程,例如走一个左方向的分支走到头了,那么要调头,在走右分支。
|
||||
|
||||
而**对于二叉搜索树,不需要回溯的过程,因为节点的有序性就帮我们确定了搜索的方向。**
|
||||
|
||||
例如要搜索元素为3的节点,**我们不需要搜索其他节点,也不需要做回溯,查找的路径已经规划好了。**
|
||||
|
||||
中间节点如果大于3就向左走,如果小于3就向右走,如图:
|
||||
|
||||
看如下图中的这颗二叉搜索树,例如要搜索元素为3的节点,我们不需要搜索其他节点,也不需要做回溯,查找的路径已经规划好了。
|
||||

|
||||
|
||||
迭代法代码如下:
|
||||
所以迭代法代码如下:
|
||||
|
||||
```
|
||||
class Solution {
|
||||
@ -81,34 +114,19 @@ public:
|
||||
};
|
||||
```
|
||||
|
||||
## C++代码
|
||||
第一次看到了如此简单的迭代法,是不是感动的痛哭流涕,哭一会~
|
||||
|
||||
### 递归
|
||||
```
|
||||
class Solution {
|
||||
public:
|
||||
TreeNode* searchBST(TreeNode* root, int val) {
|
||||
if (root == NULL || root->val == val) return root;
|
||||
if (root->val > val) return searchBST(root->left, val);
|
||||
if (root->val < val) return searchBST(root->right, val);
|
||||
return NULL;
|
||||
}
|
||||
};
|
||||
```
|
||||
# 总结
|
||||
|
||||
本篇我们介绍了二叉搜索树的遍历方式,因为二叉搜索树的有序性,遍历的时候要比普通二叉树简单很多。
|
||||
|
||||
但是一些同学很容易忽略二叉搜索树的特性,所以写出遍历的代码就未必真的简单了。
|
||||
|
||||
所以针对二叉搜索树的题目,一样要利用其特性。
|
||||
|
||||
文中我依然给出递归和迭代两种方式,可以看出写法都非常简单,就是利用了二叉搜索树有序的特点。
|
||||
|
||||
就酱,如果学到了,就转发给身边需要的同学吧!
|
||||
|
||||
### 迭代
|
||||
```
|
||||
class Solution {
|
||||
public:
|
||||
TreeNode* searchBST(TreeNode* root, int val) {
|
||||
while (root != NULL) {
|
||||
if (root->val > val) root = root->left;
|
||||
else if (root->val < val) root = root->right;
|
||||
else return root;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
> 更多算法干货文章持续更新,可以微信搜索「代码随想录」第一时间围观,关注后,回复「Java」「C++」 「python」「简历模板」「数据结构与算法」等等,就可以获得我多年整理的学习资料。
|
||||
|
Reference in New Issue
Block a user