669:修剪二叉搜索树
问题描述:给定一个二叉搜索树,同时给定最小边界L 和最大边界 R。通过修剪二叉搜索树,使得所有节点的值在[L, R]中 (R>=L) 。你可能需要改变树的根节点,所以结果应当返回修剪好的二叉搜索树的新的根节点。
解题思路
- 递归终止条件:如果当前节点为空,直接返回空。
-
修剪左子树:
- 如果当前节点的值小于最小边界L,说明当前节点及其左子树的所有节点都不在修剪范围内,因此返回修剪右子树的结果。
-
修剪右子树:
- 如果当前节点的值大于最大边界R,说明当前节点及其右子树的所有节点都不在修剪范围内,因此返回修剪左子树的结果。
-
修剪左右子树:
- 如果当前节点的值在[L, R]范围内,递归修剪当前节点的左子树和右子树。
-
返回修剪后的树:
- 返回当前节点作为修剪后树的根节点
class Solution {
public TreeNode trimBST(TreeNode root, int low, int high) {
if(root == null){
return null;
}
if(root.val<low){
return trimBST(root.right, low, high);
} else if (root.val>high) {
return trimBST(root.left, low, high);
}
root.left = trimBST(root.left, low, high);
root.right = trimBST(root.right, low, high);
return root;
}
}
题目:将有序数组转换为二叉搜索树
问题描述:将一个按照升序排列的有序数组,转换为一棵高度平衡二叉搜索树。本题中,一个高度平衡二叉树是指一个二叉树每个节点的左右两个子树的高度差的绝对值不超过 1。
解题思路
- 选择中间点作为根节点:为了保证树的高度平衡,选择数组的中间元素作为二叉搜索树的根节点。
-
递归构建左右子树:
- 左子树由数组中位于中间元素左侧的部分构建。
- 右子树由数组中位于中间元素右侧的部分构建。
- 递归终止条件:当数组的左右索引超出范围时,即左索引大于右索引时,返回空节点。
- 返回根节点:递归完成后,返回构建好的二叉搜索树的根节点。
class Solution {
public TreeNode sortedArrayToBST(int[] nums) {
return helper(nums,0,nums.length-1);
}
public TreeNode helper(int[] nums,int left,int right){
if(left>right){
return null;
}
int count = (left+right)/2;
TreeNode root = new TreeNode(nums[count]);
root.left = helper(nums,left,count-1);
root.right = helper(nums,count+1,right);
return root;
}
}
题目:把二叉搜索树转换为累加树
问题描述:给出二叉搜索树的根节点,该树的节点值各不相同,请你将其转换为累加树(Greater Sum Tree),使每个节点 node 的新值等于原树中大于或等于 node.val 的值之和。
提醒:二叉搜索树满足下列约束条件:
- 节点的左子树仅包含键小于节点键的节点。
- 节点的右子树仅包含键大于节点键的节点。
- 左右子树也必须是二叉搜索树。
解题思路
- 逆中序遍历:由于二叉搜索树的性质,逆中序遍历(右-根-左)可以保证我们先访问较大的节点。
-
累加节点值:
- 在遍历过程中,维护一个累加变量
pre
,用于记录已经访问过的节点值的累加和。 - 每访问一个节点时,将
pre
加到当前节点的值上,并更新pre
为当前节点的新值。
- 在遍历过程中,维护一个累加变量
-
递归实现:
- 递归地对右子树、当前节点、左子树进行操作,确保每个节点的值都被正确更新。
- 返回根节点:遍历完成后,返回更新后的二叉搜索树的根节点。
代码实现
class Solution {
private int pre = 0;
public TreeNode convertBST(TreeNode root) {
helper(root);
return root;
}
public void helper(TreeNode root) {
if(root==null)return;
helper(root.right);
root.val = root.val + pre;
pre = root.val;
helper(root.left);
}
}