代码随想录刷题记录day20 二叉搜索树的最近公共祖先+二叉搜索树中的插入操作+删除二叉搜索树中的节点
参考:代码随想录
235. 二叉搜索树的最近公共祖先
思想
1.用普通二叉树的思想去做了这道题目 和昨天的题解类似
2.利用二叉搜索树的特性
可以不用遍历整棵二叉搜索树了,搜索的是一条边,搜索到了就可以直接返回
如果当前节点 小于p 大于q,那么当前节点就是要找的公共祖先
如何理解这一点呢?如下图所示,只要第一次遇到了 就是最近的公共的祖先
代码
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
//因为是一颗二叉搜索树 利用二叉搜索数的特性实现
if(root==null) return null;
if(root.val>p.val &&root.val>q.val){
TreeNode left=lowestCommonAncestor(root.left,p,q);
if(left!=null) return left;
}
if(root.val<p.val && root.val<q.val){
//p q都比当前节点大 在右边
TreeNode right=lowestCommonAncestor(root.right,p,q);
if(right!=null) return right;
}
return root;
}
701. 二叉搜索树中的插入操作
思想
二叉搜索树可以永远插在叶子节点。
根据这个特性遍历到最终要插入的位置
递归终止条件 root==null 表示 遍历到了要插入的节点了,新建一个节点,同时向上返回,被root的左节点 或者root的右节点去接住这个节点。
具体左节点去接还是右节点去接住呢?比较数值的大小,利用二叉搜索树的特性,
val<root.val 左节点接住
val>root.val 右节点接住
单层递归的逻辑:
1.当前节点的值大于要插入的值,那么要往左递归,且用当前节点的左节点去接住递归的结果
2.当前节点的值小于要插入的值,要往右递归,用当前节点的右节点去接住递归的结果
3.向上返回当前的节点
代码
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;
}
}
450. 删除二叉搜索树中的节点
思想
删除节点的逻辑写在终止条件当中,又分为了5中情况
1.没找到要删除的节点 返回null
找到了要删除的节点
2.左右都为空,即找到了叶子节点 返回null
3.左空 右不为空 返回右节点
4.左不为空右为空 返回左节点
5.左右都不为空,找到右节点最左边的值cur, 让当前节点root的左子树移到cur的左子树 ,此时变成了左为空,右不为空的情况,返回右节点。
单层递归逻辑:
当前节点值大于要删除的值,那么要删除的节点就在左边,往左递归,同时需要接住删除节点后的左子树
右边也是一样的逻辑
代码
class Solution {
public TreeNode deleteNode(TreeNode root, int key) {
//删除节点的情况分为5中
if(root==null) return null;//1.没找到要删除的节点
if(root.val==key){
if(root.left==null && root.right==null){
//2.找到了叶子节点
return null;
}
else if(root.left!=null && root.right==null){
//3.左不为空 右为空的情况
return root.left;
}
else if(root.left==null && root.right!=null){
//4.左为空 右不为空
return root.right;
}
else{
//左右都不为空的情况 找到右节点的最左边的值 让这个值成为父节点
TreeNode cur=root.right;
while(cur.left!=null) {
cur=cur.left;
}
cur.left=root.left;
return root.right;
}
}
if(root.val>key) root.left= deleteNode(root.left,key);
if(root.val<key) root.right=deleteNode(root.right,key);
return root;
}
}