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天了,代码能力还是提升了不少,虽然我也很懒,每次都是做出来了就点到即止了,并不是每道题都仔细看代码随想录的攻略。自己每天做的题量也不多,就三四道的样子,还不能完完全全的理解,有时候觉得自己确实很废物。最近其实还挺闲的,但总是浪费很多时间去玩手机,前几天统计了一下,一天随随便便五六个小时,有时候真觉得自己该死啊,但总是克制不住自己。要是没有跟训练营或许这一点的做题时间都不能保证了。所以时间真的还是靠挤出来的,如果不去想着法的让自己做一点事情,最终就会和我的科研一样,啥也没有。
后面考虑看看能不能再给自己安排另外一份活,除了刷题再做点别的。每次说到这我就有点裂开,虽然是这么想的,但是最后啥也没做。太痛苦了。不敢多想了,先记录这些吧。

浙公网安备 33010602011771号