669.修剪二叉搜索数
题目链接/文章讲解: https://programmercarl.com/0669.%E4%BF%AE%E5%89%AA%E4%BA%8C%E5%8F%89%E6%90%9C%E7%B4%A2%E6%A0%91.html
视频讲解: https://www.bilibili.com/video/BV17P41177ud
本题虽然也涉及到删除节点,但是与450那题做法其实并不类似,因为450那题删除节点后我们就需要重构一下二叉树然后返回左右节点即可,但是本题我们并不是只删除一个节点,我们删除了一个节点后还是要继续判断剩余节点
思路:例如:区间在[4,7],[low,high]
- 如果待删除节点<low,根据二叉搜索树的特性,那么待删除节点的左孩子节点,就可以全部抛弃,只需要去遍历判断右孩子即可,最后将处理好的右孩子节点向上返回
- 待删除节点>high,同理
- 同时本题虽然是二叉搜索树,但是我们依然要遍历整棵树,因为我们无法根据二叉搜索树的特性来判断到底应该怎么遍历
class Solution {
// 返回值:是TreeNode,因为我们需要返回删除后的新的根节点,最后用父节点来连接,接收
// 参数:不断遍历的节点,区间
public TreeNode trimBST(TreeNode root, int low, int high) {
if(root == null) return null;
// 因为二叉搜索树的特性
// 如果删除节点 < 左边界,那么删除节点的右边界就可能符合要求
if(root.val < low){
// trimBST(root.right,low,high):表示例如以2为根节点的情况下(区间还是在[4,7])
// 左孩子我们已经可以直接抛弃,只用去判断右孩子,然后判断完之后
// 我们就直接可以把处理好的右孩子节点返回,下面会有代码即节点7.left来接收
TreeNode right = trimBST(root.right,low,high);
return right;
}
// 同理
if(root.val > high){
TreeNode left = trimBST(root.left,low,high);
return left;
}
// 在这里,就会接收到处理好的右孩子节点,
// 节点7.left直接指向了节点4(待删除节点的右孩子),这里就相当于把节点2删除,因为节点2和节点7的连接被切断
root.left = trimBST(root.left,low,high);
root.right = trimBST(root.right,low,high);
return root;
}
}
108.将有序数组转换成二叉搜索树
视频讲解:https://www.bilibili.com/video/BV1uR4y1X7qL
思路:首先题目要求,是一颗平衡二叉搜索树,那么我们就不能直接一条向右不断创建节点
- 既然要求平衡那么肯定就要不断从数组中间开始切割,在不断切割左右孩子最后创建的就是一个平衡二叉搜索树
- 返回值:我们既然要创建节点还要向上返回,那返回值就是TreeNode
- 参数:要不断切割数组,我们就可以利用双指针来切割,会比在原数组切割效率更高
- 终止条件:只要数组为空,就不在创建节点,直接返回
class Solution {
public TreeNode sortedArrayToBST(int[] nums) {
return sort(nums,0,nums.length-1);
}
public TreeNode sort(int[] nums, int start, int end){
// 如果为空节点就返回null,那么就是数组中没有元素即start > end
if(start > end) return null;
// 取数组中间索引
int mid = (start + end) >>> 1;
// 根据中间索引创建节点
TreeNode cur = new TreeNode(nums[mid]);
// 创建左孩子
cur.left = sort(nums,start,mid-1);
// 创建右孩子
cur.right = sort(nums,mid+1,end);
return cur;
}
}
538.把二叉搜索树转换为累加树
视频讲解:https://www.bilibili.com/video/BV1d44y1f7wP
题目分析:首先要理解什么是累加树,就是把比我当前节点大的值都相加起来,例如根节点4,就是把整个右孩子节点的值都要相加包括4(即:4+6+5+7+8=30)
理解后思路就非常简单,二叉搜索树利用中序遍历后本身就是有序的,那么我们只要从后往前相加就可以计算出来,在二叉树中体现出来就是,先遍历右边,再处理中间,最后遍历左边,就是跟中序遍历相反。
// 双指针法
class Solution {
// 记录前一个节点
TreeNode per = null;
public TreeNode convertBST(TreeNode root) {
if(root == null) return null;
convertBST(root.right);
if(per !=null) root.val += per.val;
per = root;
convertBST(root.left);
return root;
}
}
t.val += per.val;
per = root;
convertBST(root.left);
return root;
}
}