day22 | 235. 二叉搜索树的最近公共祖先 701.二叉搜索树中的插入操作 450.删除二叉搜索树中的节点


文章目录

  • 235. 二叉搜索树的最近公共祖先
    • 1、代码
    • 2、分析
  • 701.二叉搜索树中的插入操作
    • 1、代码1(BC)
    • 2、代码2
    • 3、分析
  • 450.删除二叉搜索树中的节点
    • 1、代码
    • 2、分析


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

1、代码

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */

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

2、分析

(1)因为本题的二叉树是二叉搜索树,所以我们要善于发现二叉树的特性与题目所要求之间的关系,易知子树的公共祖先的值必定在左右子树的值的区间范围内,且公共祖先必须是从上向下遍历第一次得到的节点值。
(2)由于判定祖先成功之后直接返回根节点而不用外加逻辑,所以本题不规定使用什么顺序的遍历方式。
(3)由于本题需要返回结果给根节点,这是一个回溯的过程,所以我们在写代码的时候需要将递归函数的返回值存取,以便函数返回值的回溯。

701.二叉搜索树中的插入操作

1、代码1(BC)

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public TreeNode pre;
    public int num = 0;
    public TreeNode insertIntoBST(TreeNode root, int val) {
        //是二叉搜索树,想到中序遍历
        //因为是中序遍历,所以val的遍历顺序是由小到大
        if(root == null) return null;
        //左
        insertIntoBST(root.left,val);
        //中
        //增加节点的两个位置
        if(root.val > val && num == 0){
            if(root.left == null){
                TreeNode node = new TreeNode(val);
                root.left = node;
            }else if(pre != null){
                while(pre.right !=null){
                    pre.right = pre;
                }
                TreeNode node = new TreeNode(val);
                pre.right = node;
            }
            num++;
        }
        pre = root;
        //对于叶子节点的处理用num

        //处理val是最大值的情况

        //右
        insertIntoBST(root.right,val);
        return root;
    }
}

2、代码2

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public TreeNode insertIntoBST(TreeNode root, int val) {
        if(root == null){
            return new TreeNode(val);
        }
        if(root.val > val){
            root.left = insertIntoBST(root.left,val);
        }else{
            root.right = insertIntoBST(root.right,val);
        }
        return root;
    }
}

3、分析

(1)本题代码1过不了的原因是对于二叉搜索树的认识过于局限,只知道二叉搜索树用于中序进行遍历的话会是按从小到大的顺序进行遍历。二叉搜索树还有一个特性是在不用遍历的情况下搜索数值:左边的子树比根节点小,右边的子树比根节点大。 可以根据本特性快速找到需要进行操作的节点,如代码2所示。

450.删除二叉搜索树中的节点

1、代码

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * } 
 */
class Solution {
    public TreeNode deleteNode(TreeNode root, int key) {
        if(root == null) return null;
        if(root.val < key){
            root.right = deleteNode(root.right,key);
        }else if(root.val > key){
            root.left = deleteNode(root.left,key);
        }else{
            if(root.left == null && root.right == null){
                return null;
            }else if(root.left == null && root.right != null){
                // root.right = root;
                return root.right;
            }else if(root.left != null && root.right == null){
                // root.left = root;
                return root.left;
            }else{
                //左不为空右不为空
                TreeNode tmp = root.right;
                while (tmp.left != null) {
                    tmp = tmp.left;
                }
                tmp.left = root.left;
                return root.right;
            }
        }
        return root;
    }
}

2、分析

(1)本题是删除二叉搜索树的节点,所以我们需要先找到需要删除的节点,由此我们可以利用二叉搜索树的第二个特性将节点找出来。
(2)本题我们需要从叶子节点到树,即由小到大的层面将我们需要删除的节点的情况找出来。即00,01,10,11。
(3)本题需要学到的是:在对二叉树的节点进行删除的操作中,我们可以通过返回值或者通过递归直接删除节点,比如:

return root.right;

在这里我们将这个函数的返回值返回这个节点的右节点,由此跳过该节点的返回,可以认为是删除了这个节点。
(4)代码:

                while (tmp.left != null) {
                    tmp = tmp.left;
                }
                tmp.left = root.left;

这里的情况需要我们对二叉树的各种情况进行仔细的考虑。

你可能感兴趣的:(算法,leetcode,职场和发展)