day20 力扣235. 二叉搜索树的最近公共祖先 力扣701.二叉搜索树中的插入操作 力扣450.删除二叉搜索树中的节点
二叉搜索树的最近公共祖先
给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
例如,给定如下二叉搜索树: root = [6,2,8,0,4,7,9,null,null,3,5]
示例 1:
输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8 输出: 6 解释: 节点2
和节点8
的最近公共祖先是6。
示例 2:
输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 4 输出: 2 解释: 节点2
和节点4
的最近公共祖先是2
, 因为根据定义最近公共祖先节点可以为节点本身。说明:
- 所有节点的值都是唯一的。
- p、q 为不同节点且均存在于给定的二叉搜索树中。
我们可以得知,如果一个节点的值小于当前节点的值,且另一个节点的值大于当前节点的值,则,此节点就是最近公共祖先。
如果p,q俩节点的值均小于当前节点的值,则q,p在此节点的左子树上,就需要判断左孩子是否为空。(相当于把最近祖先的值一直往上传递到root节点)
如果p,q俩节点的值均大于当前节点的值,则q,p在此节点的右子树上,就需要判断右孩子是否为空。
/*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode(int x) : val(x), left(NULL), right(NULL) {}* };*/class Solution {
public:TreeNode* traversal(TreeNode* cur, TreeNode* p, TreeNode* q){if(cur==nullptr) return NULL;if(cur->val>p->val&&cur->val>q->val){TreeNode* left = traversal(cur->left,p,q);if(left!=nullptr) return left;}if(cur->val<p->val&&cur->val<q->val){TreeNode* right = traversal(cur->right,p,q);if(right!=nullptr) return right;}return cur;}TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {return traversal(root,p,q);}
};
二叉搜索树中的插入操作
给定二叉搜索树(BST)的根节点
root
和要插入树中的值value
,将值插入二叉搜索树。 返回插入后二叉搜索树的根节点。 输入数据 保证 ,新值和原始二叉搜索树中的任意节点值都不同。注意,可能存在多种有效的插入方式,只要树在插入后仍保持为二叉搜索树即可。 你可以返回 任意有效的结果 。
示例 1:
输入:root = [4,2,7,1,3], val = 5 输出:[4,2,7,1,3,5] 解释:另一个满足题目要求可以通过的树是:
示例 2:
输入:root = [40,20,60,10,30,50,70], val = 25 输出:[40,20,60,10,30,50,70,null,null,25]示例 3:
输入:root = [4,2,7,1,3,null,null,null,null,null,null], val = 5 输出:[4,2,7,1,3,5]提示:
- 树中的节点数将在
[0, 104]
的范围内。-108 <= Node.val <= 108
- 所有值
Node.val
是 独一无二 的。-108 <= val <= 108
- 保证
val
在原始BST中不存在。
乍一看无从下手,实际上还是很简单的。
他已说有多种解法,那我们就可以用最简单的,把所有的val加在叶子节点上,就不需要改变二叉树结构了。
如果当前节点为空,那我们就new一个新节点,值为val。
然后判断这个val和当前节点值的大小,从而让新节点与原二叉树建立联系(即cur->left/right = ```)
/*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}* };*/
class Solution {
public:TreeNode* insertIntoBST(TreeNode* root, int val) {if(root==nullptr){TreeNode* cur = new TreeNode(val);return cur;}if(root->val>val){root->left = insertIntoBST(root->left,val); }if(root->val<val){root->right = insertIntoBST(root->right,val); }return root; }
};
删除二叉搜索树中的节点
给定一个二叉搜索树的根节点 root 和一个值 key,删除二叉搜索树中的 key 对应的节点,并保证二叉搜索树的性质不变。返回二叉搜索树(有可能被更新)的根节点的引用。
一般来说,删除节点可分为两个步骤:
- 首先找到需要删除的节点;
- 如果找到了,删除它。
示例 1:
输入:root = [5,3,6,2,4,null,7], key = 3 输出:[5,4,6,2,null,null,7] 解释:给定需要删除的节点值是 3,所以我们首先找到 3 这个节点,然后删除它。 一个正确的答案是 [5,4,6,2,null,null,7], 如下图所示。 另一个正确答案是 [5,2,6,null,4,null,7]。
示例 2:
输入: root = [5,3,6,2,4,null,7], key = 0 输出: [5,3,6,2,4,null,7] 解释: 二叉树不包含值为 0 的节点示例 3:
输入: root = [], key = 0 输出: []提示:
- 节点数的范围
[0, 104]
.-105 <= Node.val <= 105
- 节点值唯一
root
是合法的二叉搜索树-105 <= key <= 105
分为五种情况:
第一种:没找到key值(该节点为空节点)
第二种 :key值在叶子节点上。
第三种:key不在叶子节点上,但存在左子树,无右孩子。
第四种: key不在叶子节点上,但存在右子树,无左孩子。
第五种:key不在叶子节点上,有左右子树。(这种情况我们可以把左子树放在右子树最深深度的左侧节点的左孩子位置上)
明白了情况划分,代码就好写很多。
/*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}* };*/
class Solution {
public:TreeNode* deleteNode(TreeNode* root, int key) {if(root==nullptr)return nullptr;if(root->val==key){if(root->left==nullptr&&root->right==nullptr)return nullptr;else if(root->left==nullptr&&root->right!=nullptr)return root->right;else if(root->right==nullptr&&root->left!=nullptr)return root->left;else{TreeNode* cur = root->right;while(cur->left!=nullptr){cur = cur->left;}cur->left = root->left;return root->right;}}if(key<root->val) root->left = deleteNode(root->left,key);if(key>root->val) root->right = deleteNode(root->right,key);return root;}
};