Day 21 二叉树part08 | 二叉树最终章,暂时告一段落

669. 修剪二叉搜索树

先贴上我自己的答案吧,一次写出来了,但其实很多地方都应该进行优化,没有完全利用好搜索树的性质。先看注释,理清自己的思路吧。

总体思路就是先对左右两个子树修剪,再根据根节点是否需要删除进行重构。这一操作和昨天的删除二叉搜索树中的节点操作是类似的。重构部分最复杂的就是左右子树都不为空的情况,由于不能破坏掉原有树的父子关系,因此我使用将左子树挂在右子树中值最小的节点的左子树上(因为左子树中的所有节点都小于右子树中的最小值)。

class Solution {
    public TreeNode trimBST(TreeNode root, int low, int high) {
        if(root == null) return root;
        root.left = trimBST(root.left, low, high); //左
        root.right = trimBST(root.right, low, high); //右
        if(root.val >= low && root.val <= high) return root; //不需要处理
        if(root.right == null) return root.left;
        if(root.left == null) return root.right;
        TreeNode rightMin = root.right; //左右子树都不为空
        while(rightMin.left != null){ //找到右子树中最小的节点
            rightMin = rightMin.left;
        }
        rightMin.left = root.left; //把左子树作为右子树中最小值节点的左子树
        return root.right;
    }
}

显然我的方法还是复杂了,有更好的剪枝方法,这里我附上官解。我自己理解,官解也是后序遍历的方法,但是剪枝做的更好,显然理解起来也比我的更容易。

class Solution {
    public TreeNode trimBST(TreeNode root, int low, int high) {
        //这三行代表了修剪的操作,虽然代码很简单,但其实还挺难想到的
        if(root == null) return root;
        if(root.val > high) return trimBST(root.left, low, high); //若根节点值比high还大,说明整个右子树都是大于high的,则只需要将左子树处理后的结果返回即可
        if(root.val < low) return trimBST(root.right, low, high); //同理
        
        //下面三行进行后序遍历,先修剪左右子树,再返回根节点即可
        root.left = trimBST(root.left, low, high);
        root.right = trimBST(root.right, low, high);
        return root;
    }
}

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

这道题和前面构造二叉树的题目基本都是类似的,都是将数组划分,递归的创建左右子树,与根节点进行链接就完成了。由于是有序数组,很显然使用二分进行划分即可,一定能保证生成的树是平衡的。注意区间的使用前后一定要统一,我这里全部使用了左闭右闭的写法。

class Solution {
    public TreeNode sortedArrayToBST(int[] nums) {
        return constructBST(nums, 0, nums.length-1); //左闭右闭
    }
    public TreeNode constructBST(int[] nums, int left, int right){
        if(left > right) return null;
        int mid = (left + right) / 2;
        TreeNode root = new TreeNode(nums[mid]);
        root.left = constructBST(nums, left, mid-1);
        root.right = constructBST(nums, mid+1, right);
        return root;
    }
}

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

这道题现在做起来就很容易了。唯一需要注意的点就是累加是针对于大于等于当前节点的值的节点,因此需要采用右中左的遍历方法,先遍历右子树。剩下的就是套用中序遍历的模板,不论是递归还是迭代应该都是没问题的,使用pre记录上一个访问过的节点,进行累加即可。

class Solution {
    TreeNode pre;
    public TreeNode convertBST(TreeNode root) {
        if(root == null) return null;
        if(root.right != null) convertBST(root.right);
        if(pre != null) root.val += pre.val;
        pre = root;
        if(root.left != null) convertBST(root.left);
        return root; 
    }
}

不知不觉跟着代码随想录算法训练营已经刷题第20天了,代码能力还是提升了不少,虽然我也很懒,每次都是做出来了就点到即止了,并不是每道题都仔细看代码随想录的攻略。自己每天做的题量也不多,就三四道的样子,还不能完完全全的理解,有时候觉得自己确实很废物。最近其实还挺闲的,但总是浪费很多时间去玩手机,前几天统计了一下,一天随随便便五六个小时,有时候真觉得自己该死啊,但总是克制不住自己。要是没有跟训练营或许这一点的做题时间都不能保证了。所以时间真的还是靠挤出来的,如果不去想着法的让自己做一点事情,最终就会和我的科研一样,啥也没有。

后面考虑看看能不能再给自己安排另外一份活,除了刷题再做点别的。每次说到这我就有点裂开,虽然是这么想的,但是最后啥也没做。太痛苦了。不敢多想了,先记录这些吧。

posted @ 2024-07-23 17:40  12点不睡觉还想干啥?  阅读(19)  评论(0)    收藏  举报