算法训练day23|二叉树 part9

文章讲述了如何在二叉搜索树中进行节点删除(trimBST),使用递归和迭代方法处理范围限制,包括有序数组转换为二叉搜索树、累加树构建以及计算最大深度、最小深度和众数等问题。

669. 修剪二叉搜索树

1.删除节点可以靠返回值来操作,返回其子节点就是删除了该节点

所以返回值选择为节点,要处理空节点,否则正常范围内返回根节点

    public TreeNode trimBST(TreeNode root, int low, int high) {
        if (root == null) {
            return null;
        }

2. 需要遍历整颗树

3. 遇到比范围小的根节点,删除该节点和其左子树(左子树比根节点小),返回右子树。但是右子树中可能还存在不符合范围的值,所以应该返回右子树的遍历函数(遍历整颗树)

        if (root.val < low) {
            return trimBST(root.right, low, high);
        }

4. 遇到比范围大的根节点同理

        if (root.val > high) {
            return trimBST(root.left, low, high);
        }

5.遇到在范围内的根节点,不需要操作,直接按照整数遍历走就可以了

        // root在[low,high]范围内
        root.left = trimBST(root.left, low, high);
        root.right = trimBST(root.right, low, high);
        return root;

迭代法

class Solution {
    //iteration
    public TreeNode trimBST(TreeNode root, int low, int high) {
        if(root == null)
            return null;
        //找到范围阈值内的节点
        while(root != null && (root.val < low || root.val > high)){
            if(root.val < low)
                root = root.right;
            else
                root = root.left;
        }

        TreeNode curr = root;
        //往左边找,当cur.left小于阈值范围时删除cur.left及其左节点cur.left.left,将其右节点的值赋予左节点(cur.left = cur.left.right)
        //删除之后,因为cur.left.right仍然存在不有效节点的可能,接着向左遍历
        //deal with root's left sub-tree, and deal with the value smaller than low.
        while(curr != null){
            while(curr.left != null && curr.left.val < low){
                curr.left = curr.left.right;
            }
            curr = curr.left;
        }
        //go back to root;重新回到范围内
        curr = root;
        //对右边做同样的操作
        //deal with root's righg sub-tree, and deal with the value bigger than high.
        while(curr != null){
            while(curr.right != null && curr.right.val > high){
                curr.right = curr.right.left;
            }
            curr = curr.right;
        }
        return root;
    }
}

108.将有序数组转换为二叉搜索树

debug:递归法如果stack overflow可能是进入了死循环,没有说明有关终止条件的部分出了问题

对于区间定义的循环不变量

通过递归函数的返回值来增删二叉树

538.把二叉搜索树转换为累加树

有序数组倒叙->中序遍历反过来右中左

class Solution {
    int sum;
    public TreeNode convertBST(TreeNode root) {
        sum = 0;
        convertBST1(root);
        return root;
    }

    // 按右中左顺序遍历,累加即可
    public void convertBST1(TreeNode root) {
        if (root == null) {
            return;
        }
        convertBST1(root.right);
        sum += root.val;
        root.val = sum;
        convertBST1(root.left);
    }
}

//迭代法
class Solution {
    //DFS iteraion統一迭代法
    public TreeNode convertBST(TreeNode root) {
        int pre = 0;
        Stack<TreeNode> stack = new Stack<>();
        if(root == null) //edge case check
            return null;

        stack.add(root);

        while(!stack.isEmpty()){
            TreeNode curr = stack.peek();
            //curr != null的狀況,只負責存node到stack中
            if(curr != null){ 
                stack.pop();
                if(curr.left != null)       //左
                    stack.add(curr.left);
                stack.add(curr);            //中
                stack.add(null);
                if(curr.right != null)      //右
                    stack.add(curr.right);
            }else{
            //curr == null的狀況,只負責做單層邏輯
                stack.pop();
                TreeNode temp = stack.pop();
                temp.val += pre;
                pre = temp.val;
            }
        }
        return root;
    }
}

二叉树总结:

图源:代码随想录

class Solution {
    /**
     * 递归法,相比求MaxDepth要复杂点
     * 因为最小深度是从根节点到最近**叶子节点**的最短路径上的节点数量
     */
    public int minDepth(TreeNode root) {
        if (root == null) {
            return 0;
        }
        int leftDepth = minDepth(root.left);
        int rightDepth = minDepth(root.right);
        if (root.left == null) {
            return rightDepth + 1;
        }
        if (root.right == null) {
            return leftDepth + 1;
        }
        // 左右结点都不为null
        //都为null已经被包含,其实就是1
        return Math.min(leftDepth, rightDepth) + 1;
    }
}

求二叉搜索树的众数(opens new window)

  • 递归:中序,清空结果集的技巧,遍历一遍便可求众数集合

二叉搜索树的公共祖先问题

​​

  • 递归:顺序无所谓,如果节点的数值在目标区间就是最近公共祖先
  • 迭代:按序遍历
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值