「leetcode」701. 二叉搜索树中的插入操作:【递归法】【迭代法】详解
本文 https://github.com/youngyangyang04/leetcode-master 已经收录,里面还有leetcode刷题攻略、各个类型经典题目刷题顺序、思维导图,可以fork到自己仓库,有空看一看一定会有所收获,如果对你有帮助也给一个star支持一下吧!
701.二叉搜索树中的插入操作
链接:https://leetcode-cn.com/problems/insert-into-a-binary-search-tree/
给定二叉搜索树(BST)的根节点和要插入树中的值,将值插入二叉搜索树。 返回插入后二叉搜索树的根节点。 输入数据保证,新值和原始二叉搜索树中的任意节点值都不同。
注意,可能存在多种有效的插入方式,只要树在插入后仍保持为二叉搜索树即可。 你可以返回任意有效的结果。
提示:
- 给定的树上的节点数介于 0 和 10^4 之间
- 每个节点都有一个唯一整数值,取值范围从 0 到 10^8
- -10^8 <= val <= 10^8
- 新值和原始二叉搜索树中的任意节点值都不同
思路
其实这道题目其实是一道简单题目,但是题目中的提示:有多种有效的插入方式,还可以重构二叉搜索树,一下子吓退了不少人,瞬间感觉题目复杂了很多。
其实可以不考虑题目中提示所说的改变树的结构的插入方式。
如下演示视频中可以看出:只要按照二叉搜索树的规则去遍历,遇到空节点就插入节点就可以了。
例如插入元素10 ,需要找到末尾节点插入便可,一样的道理来插入元素15,插入元素0,插入元素6,需要调整二叉树的结构么? 并不需要。。
只要遍历二叉搜索树,找到空节点 插入元素就可以了,那么这道题其实就简单了。
接下来就是遍历二叉搜索树的过程了。
递归
递归三部曲:
- 确定递归函数参数以及返回值
参数就是根节点指针,以及要插入元素,这里递归函数要不要有返回值呢?
可以有,也可以没有,但递归函数如果没有返回值的话,实现是比较麻烦的,下面也会给出其具体实现代码。
有返回值的话,可以利用返回值完成新加入的节点与其父节点的赋值操作。(下面会进一步解释)
递归函数的返回类型为节点类型TreeNode * 。
代码如下:
TreeNode* insertIntoBST(TreeNode* root, int val)
- 确定终止条件
终止条件就是找到遍历的节点为null的时候,就是要插入节点的位置了,并把插入的节点返回。
代码如下:
if (root == NULL) {TreeNode* node = new TreeNode(val);return node;
}
这里把添加的节点返回给上一层,就完成了父子节点的赋值操作了,详细再往下看。
- 确定单层递归的逻辑
此时要明确,需要遍历整棵树么?
别忘了这是搜索树,遍历整颗搜索树简直是对搜索树的侮辱,哈哈。
搜索树是有方向了,可以根据插入元素的数值,决定递归方向。
代码如下:
if (root->val > val) root->left = insertIntoBST(root->left, val);
if (root->val < val) root->right = insertIntoBST(root->right, val);
return root;
到这里,大家应该能感受到,如何通过递归函数返回值完成了新加入节点的父子关系赋值操作了,下一层将加入节点返回,本层用root->left或者root->right将其接住。
整体代码如下:
class Solution {
public:TreeNode* insertIntoBST(TreeNode* root, int val) {if (root == NULL) {TreeNode* node = new TreeNode(val);return node;}if (root->val > val) root->left = insertIntoBST(root->left, val);if (root->val < val) root->right = insertIntoBST(root->right, val);return root;}
};
可以看出代码并不复杂。
刚刚说了递归函数不用返回值也可以,找到插入的节点位置,直接让其父节点指向插入节点,结束递归,也是可以的。
那么递归函数定义如下:
TreeNode* parent; // 记录遍历节点的父节点
void traversal(TreeNode* cur, int val)
没有返回值,需要记录上一个节点(parent),遇到空节点了,就让parent左孩子或者右孩子指向新插入的节点。然后结束递归。
代码如下:
class Solution {
private:TreeNode* parent;void traversal(TreeNode* cur, int val) {if (cur == NULL) {TreeNode* node = new TreeNode(val);if (val > parent->val) parent->right = node;else parent->left = node;return;}parent = cur;if (cur->val > val) traversal(cur->left, val);if (cur->val < val) traversal(cur->right, val);return;}public:TreeNode* insertIntoBST(TreeNode* root, int val) {parent = new TreeNode(0);if (root == NULL) {root = new TreeNode(val);}traversal(root, val);return root;}
};
可以看出还是麻烦一些的。
我之所以举这个例子,是想说明通过递归函数的返回值完成父子节点的赋值是可以带来便利的。
网上千变一律的代码,可能会误导大家认为通过递归函数返回节点 这样的写法是天经地义,其实这里是有优化的!
迭代
再来看看迭代法,对二叉搜索树迭代写法不熟悉,可以看这篇:二叉树:二叉搜索树登场!
在迭代法遍历的过程中,需要记录一下当前遍历的节点的父节点,这样才能做插入节点的操作。
在二叉树:搜索树的最小绝对差和二叉树:我的众数是多少?中,都是用了记录pre和cur两个指针的技巧,本题也是一样的。
代码如下:
class Solution {
public:TreeNode* insertIntoBST(TreeNode* root, int val) {if (root == NULL) {TreeNode* node = new TreeNode(val);return node;}TreeNode* cur = root;TreeNode* parent = root; // 这个很重要,需要记录上一个节点,否则无法赋值新节点while (cur != NULL) {parent = cur;if (cur->val > val) cur = cur->left;else cur = cur->right;}TreeNode* node = new TreeNode(val);if (val < parent->val) parent->left = node;// 此时是用parent节点的进行赋值else parent->right = node;return root;}
};
总结
首先在二叉搜索树中的插入操作,大家不用恐惧其重构搜索树,其实根本不用重构。
然后在递归中,我们重点讲了如果通过递归函数的返回值完成新加入节点和其父节点的赋值操作,并强调了搜索树的有序性。
最后依然给出了迭代的方法,迭代的方法就需要记录当前遍历节点的父节点了,这个和没有返回值的递归函数实现的代码逻辑是一样的。
我是程序员Carl,利用工作之余重刷leetcode,更多精彩算法文章尽在:代码随想录,关注后,回复「Java」「C++」「python」「简历模板」等等,有我整理多年的学习资料,可以加我微信,备注「简单自我介绍」+「组队刷题」,拉你进入刷题群(无任何广告,纯个人分享),每天一道经典题目分析,我选的每一道题目都不是孤立的,而是由浅入深一脉相承的,如果跟住节奏每篇连续着看,定会融会贯通。
以下资料希望对你有帮助:
- 学习资料以及我的开源项目
- 我的B站视频:算法和编程语言的讲解
- leetcode刷题攻略
- 程序员应该如何写简历(附简历模板)
- 一线互联网公司技术面试的流程以及注意事项
- C++面试&C++学习指南知识点整理
如果感觉题解对你有帮助,不要吝啬给一个
目录 问题描述: 实现代码与解析: 递归: 原理思路: 迭代: 原理思路: 问题描述: 给定二叉搜索树(BST)的根节点 root 和要插入树中的值 value ,将值插入二叉搜索树. 返回插入后二叉 ... 文章目录 LeetCode 236. 二叉树的最近公共祖先 题目讲解 思路 LeetCode 701.二叉搜索树中的插入操作 题目讲解 思路 LeetCode 450.删除二叉搜索树中的节点 题目讲解 ... X.<tag-数组和二分查找>-lt.xx-xxxxxx + lt.xx-xxxxxx lt.701. 二叉搜索树中的插入操作 [案例需求] [思路分析一, 带返回值的递归] [代码实现] ... 文章目录 235. 二叉搜索树的最近公共祖先 思路 代码 困难 701.二叉搜索树中的插入操作 思路 代码 450.删除二叉搜索树中的节点 思路 代码 困难 今日收获 235. 二叉搜索树的最近公共祖 ... 1. 题目 给定二叉搜索树(BST)的根节点和要插入树中的值,将值插入二叉搜索树. 返回插入后二叉搜索树的根节点. 保证原始二叉搜索树中不存在新值. 注意,可能存在多种有效的插入方式,只要树在插入后仍 ... 给定二叉搜索树(BST)的根节点 root 和要插入树中的值 value ,将值插入二叉搜索树. 返回插入后二叉搜索树的根节点. 输入数据 保证 ,新值和原始二叉搜索树中的任意节点值都不同.注意,可能 ... 给定二叉搜索树(BST)的根节点和要插入树中的值,将值插入二叉搜索树. 返回插入后二叉搜索树的根节点. 保证原始二叉搜索树中不存在新值. 注意,可能存在多种有效的插入方式,只要树在插入后仍保持为二叉搜 ... 题目链接:力扣 插入一个数,就是先找到插入位置,然后进行插入操作. 思路:递归 递归函数声明: TreeNode* insertIntoBST(TreeNode* root, int val); 递归 ... 迭代法 /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode ... 一.题目要求 给定二叉搜索树(BST)的根节点 root 和要插入树中的值 value,将值插入二叉搜索树,返回插入后二叉搜索树的根节点,输入数据保证,新值和原始二叉搜索树中的任意节点值都不同. 注意 ...「leetcode」701. 二叉搜索树中的插入操作:【递归法】【迭代法】详解相关推荐
最新文章
热门文章