• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

算法训练营 day22 二叉树 二叉搜索树的最近公共祖先 二叉搜索树的插入操作 删除二叉搜索树的节点

武飞扬头像
还是选择了面包
帮助1

算法训练营 day22 二叉树 二叉搜索树的最近公共祖先 二叉搜索树中的插入操作 删除二叉搜索树中的节点

二叉搜索树的最近公共祖先

235. 二叉搜索树的最近公共祖先 - 力扣(LeetCode)

给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。

百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

因为是有序树,所有 如果 中间节点是 q 和 p 的公共祖先,那么 中节点的数组 一定是在 [p, q]区间的。即 中节点 > p && 中节点 < q 或者 中节点 > q && 中节点 < p。

递归法

  • 确定递归函数返回值以及参数

    参数就是当前节点,以及两个结点 p、q。

    返回值是要返回最近公共祖先,所以是TreeNode 。

  • 确定终止条件

    遇到空返回就可以了

  • 确定单层递归的逻辑

    在遍历二叉搜索树的时候就是寻找区间[p.val, q.val](注意这里是左闭又闭)

    那么如果 cur.val 大于 p.val,同时 cur.val 大于q.val,那么就应该向左遍历(说明目标区间在左子树上)。

class Solution {
    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) {
           TreeNode right = lowestCommonAncestor(root.right, p, q);
           if (right!=null) return right;
        }
        return root;
    }
}

//精简
class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if (root.val > p.val && root.val > q.val) return lowestCommonAncestor(root.left,p,q);
        if (root.val < p.val && root.val < q.val) return lowestCommonAncestor(root.right,p,q);
        return root;
    }
}
学新通

迭代法

class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        while (true){
            if (root.val>p.val&&root.val>q.val) root = root.left;
            else if (root.val<p.val&&root.val<q.val) root = root.right;
            else break;
        }
        return root;
    }
}

二叉搜索树中的插入操作

701. 二叉搜索树中的插入操作 - 力扣(LeetCode)

给定二叉搜索树(BST)的根节点 root 和要插入树中的值 value ,将值插入二叉搜索树。 返回插入后二叉搜索树的根节点。 输入数据 保证 ,新值和原始二叉搜索树中的任意节点值都不同。

注意,可能存在多种有效的插入方式,只要树在插入后仍保持为二叉搜索树即可。 你可以返回 任意有效的结果 。

如下演示视频中可以看出:只要按照二叉搜索树的规则去遍历,遇到空节点就插入节点就可以了。

学新通

递归法

class Solution {
    public TreeNode insertIntoBST(TreeNode root, int val) {
        if (root == null) // 如果当前节点为空,也就意味着val找到了合适的位置,此时创建节点直接返回。
            return new TreeNode(val);
            
        if (root.val < val){
            root.right = insertIntoBST(root.right, val); // 递归创建右子树
        }else if (root.val > val){
            root.left = insertIntoBST(root.left, val); // 递归创建左子树
        }
        return root;
    }
}

迭代法

class Solution {
    public static TreeNode insertIntoBST(TreeNode root, int val) {
        if (root == null) return new TreeNode(val);
        TreeNode result = root;
        TreeNode pre=null;

        while (root != null) {
            pre = root;//保存前一个节点
            if (root.val < val) root = root.right;
            else if (root.val > val) root = root.left;
        }
        if (root==null){
            if (pre.val > val) {
                pre.left = new TreeNode(val);
            } else {
                pre.right = new TreeNode(val);
            }
        }
        return result;
    }
}
学新通

删除二叉搜索树中的节点

450. 删除二叉搜索树中的节点 - 力扣(LeetCode)

给定一个二叉搜索树的根节点 root 和一个值 key,删除二叉搜索树中的 key 对应的节点,并保证二叉搜索树的性质不变。返回二叉搜索树(有可能被更新)的根节点的引用。

一般来说,删除节点可分为两个步骤:

首先找到需要删除的节点;
如果找到了,删除它。

这里就把二叉搜索树中删除节点遇到的情况都搞清楚。

有以下五种情况:

  • 第一种情况:没找到删除的节点,遍历到空节点直接返回了
  • 找到删除的节点
    • 第二种情况:左右孩子都为空(叶子节点),直接删除节点, 返回NULL为根节点
    • 第三种情况:删除节点的左孩子为空,右孩子不为空,删除节点,右孩子补位,返回右孩子为根节点
    • 第四种情况:删除节点的右孩子为空,左孩子不为空,删除节点,左孩子补位,返回左孩子为根节点
    • 第五种情况:左右孩子节点都不为空,则将删除节点的左子树头结点(左孩子)放到删除节点的右子树的最左面节点的左孩子上,返回删除节点右孩子为新的根节点。

学新通

递归法

class Solution {
    public TreeNode deleteNode(TreeNode root, int key) {
        //第一种情况没有找到目标值
        if (root==null) return null;
        if (root.val==key){
            //第二种情况目标值为叶子节点
            if (root.left==null&&root.right==null){
                return null;
            }
            //第三种情况目标值左为空 右不为空
            else if (root.left!=null&&root.right==null){
                return root.left;
            }
            //第四种情况目标值右为空 左不为空
            else if (root.right!=null&&root.right==null){
                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;
    }
}
学新通

迭代法

class Solution {
    public TreeNode deleteNode(TreeNode root, int key) {
        if (root == null) return null;
        TreeNode cur = root;
        TreeNode pre = null;
        while (cur != null) {
            if (cur.val == key) break;
            pre = cur;
            if (cur.val > key) cur = cur.left;
            else if (cur.val < key) cur = cur.right;
        }
        if (pre == null) {
            return deleteOneNode(cur);
        }
        if (pre.left != null && pre.left.val == key) {
            pre.left = deleteOneNode(cur);
        }
        if (pre.right != null && pre.right.val == key) {
            pre.right = deleteOneNode(cur);
        }
        return root;
    }

    private TreeNode deleteOneNode(TreeNode root) {
            //第二种情况目标值为叶子节点
            if (root.left==null&&root.right==null){
                return null;
            }
            //第三种情况目标值左为空 右不为空
            else if (root.left!=null&&root.right==null){
                return root.left;
            }
            //第四种情况目标值右为空 左不为空
            else if (root.right!=null&&root.right==null){
                return root.right;
            }
            //第五种情况目标值左右都不为空
            else {
                TreeNode cur = root.right;
                while (cur.left!=null) cur = cur.left;
                cur.left = root.left;
                return root.right;
            }
	}
}
学新通

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgghjbe
系列文章
更多 icon
同类精品
更多 icon
继续加载