算法训练营第二十三天(二叉树完结)
669. 修剪二叉搜索树
力扣题目链接(opens new window)
题目
给定一个二叉搜索树,同时给定最小边界L 和最大边界 R。通过修剪二叉搜索树,使得所有节点的值在[L, R]中 (R>=L) 。你可能需要改变树的根节点,所以结果应当返回修剪好的二叉搜索树的新的根节点。
解答
自己写的递归
class Solution {
public TreeNode trimBST(TreeNode root, int low, int high) {
if (root == null)
return null;
if (root.val == low){
root.left = null;
root.right = trimBST(root.right,low,high);
}else if (root.val == high){
root.right = null;
root.left = trimBST(root.left,low,high);
}else if (root.val > low && root.val < high){
root.left = trimBST(root.left,low,high);
root.right = trimBST(root.right,low,high);
}else if (root.val < low)
root = trimBST(root.right,low,high);
else
root = trimBST(root.left,low,high);
return root;
}
}
简化递归
class Solution {
public TreeNode trimBST(TreeNode root, int low, int high) {
if (root == null)
return null;
if (root.val < low)
root = trimBST(root.right,low,high);//左子树和根都不要了
else if (root.val > high)
root = trimBST(root.left,low,high);//右子树和根都不要了
else {
// root在[low,high]范围内
root.left = trimBST(root.left,low,high);
root.right = trimBST(root.right,low,high);
}
return root;
}
}
迭代(看下图就理解了)
class Solution {
public TreeNode trimBST(TreeNode root, int low, int high) {
if(root == null)
return null;
// 处理头结点,让root移动到[L, R] 范围内,注意是左闭右闭
while(root != null && (root.val < low || root.val > high)){
if(root.val < low)
root = root.right;// 小于L往右走
else
root = root.left;// 大于R往左走
}
TreeNode curr = root;
// 此时root已经在[L, R] 范围内,处理左孩子元素小于L的情况
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;
// 此时root已经在[L, R] 范围内,处理右孩子大于R的情况
while(curr != null){
while(curr.right != null && curr.right.val > high){
curr.right = curr.right.left;
}
curr = curr.right;
}
return root;
}
}
108.将有序数组转换为二叉搜索树
力扣题目链接(opens new window)
题目
将一个按照升序排列的有序数组,转换为一棵高度平衡二叉搜索树。
本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1。
示例:
解答
使用新的空间
class Solution {
public TreeNode sortedArrayToBST(int[] nums) {
if (nums.length == 0)
return null;
int midIndex = nums.length / 2;
TreeNode root = new TreeNode(nums[midIndex]);
root.left = sortedArrayToBST(Arrays.copyOfRange(nums,0,midIndex));
root.right = sortedArrayToBST(Arrays.copyOfRange(nums,midIndex + 1,nums.length));
return root;
}
}
使用索引(左闭右开)
class Solution {
public TreeNode sortedArrayToBST(int[] nums) {
return sortedArrayToBST(nums, 0, nums.length);
}
//左闭右开
public TreeNode sortedArrayToBST(int[] nums, int left, int right) {
if (left >= right) {
return null;
}
if (right - left == 1) {
return new TreeNode(nums[left]);
}
int mid = left + (right - left) / 2;
TreeNode root = new TreeNode(nums[mid]);
root.left = sortedArrayToBST(nums, left, mid);
root.right = sortedArrayToBST(nums, mid + 1, right);
return root;
}
}
538.把二叉搜索树转换为累加树
力扣题目链接(opens new window)
题目
给出二叉 搜索 树的根节点,该树的节点值各不相同,请你将其转换为累加树(Greater Sum Tree),使每个节点 node 的新值等于原树中大于或等于 node.val 的值之和。
提醒一下,二叉搜索树满足下列约束条件:
节点的左子树仅包含键 小于 节点键的节点。 节点的右子树仅包含键 大于 节点键的节点。 左右子树也必须是二叉搜索树。
示例 1:
- 输入:[4,1,6,0,2,5,7,null,null,null,3,null,null,null,8]
- 输出:[30,36,21,36,35,26,15,null,null,null,33,null,null,null,8]
示例 2:
- 输入:root = [0,null,1]
- 输出:[1,null,1]
示例 3:
- 输入:root = [1,0,2]
- 输出:[3,3,2]
示例 4:
- 输入:root = [3,2,4,1]
- 输出:[7,9,4,10]
提示:
- 树中的节点数介于 0 和 104 之间。
- 每个节点的值介于 -104 和 104 之间。
- 树中的所有值 互不相同 。
- 给定的树为二叉搜索树
解答
- 采取中序遍历,不过是右中左,相当于从最大到最小遍历
- 对于每一个结点,他的值都等于他之前遍历的所有的值的和
- 下面的sum其实也相当于双指针中的pre,初始状态pre指向空,cur指向最右侧结点
递归
class Solution {
int sum = 0;
public TreeNode convertBST(TreeNode root) {
travel(root);
return root;
}
private void travel(TreeNode root){
if (root == null)
return;
//右中左
travel(root.right);
root.val += sum;
sum = root.val;
travel(root.left);
}
}
//不好理解
class Solution {
public TreeNode convertBST(TreeNode root) {
travel(root,0);
return root;
}
private int travel(TreeNode root,int sum){
if (root == null)
return sum;
//右中左
root.val += travel(root.right,sum);
return travel(root.left,root.val);//每次执行完都是为下一轮做准备
}
}
迭代
class Solution {
public TreeNode convertBST(TreeNode root) {
//右中左
Stack<TreeNode> stack = new Stack<>();
int sum = 0;
TreeNode cur = root;
//右中左
while (!stack.isEmpty() || cur != null){
while (cur != null){
stack.push(cur);
cur = cur.right;
}
cur = stack.pop();
cur.val += sum;
sum = cur.val;
cur = cur.left;
}
return root;
}
}