669. 修剪二叉搜索树
给你二叉搜索树的根节点
root,同时给定最小边界low和最大边界high。通过修剪二叉搜索树,使得所有节点的值在[low, high]中。修剪树 不应该 改变保留在树中的元素的相对结构 (即,如果没有被移除,原有的父代子代关系都应当保留)。 可以证明,存在 唯一的答案 。
所以结果应当返回修剪好的二叉搜索树的新的根节点。注意,根节点可能会根据给定的边界发生改变。
思路
对于二叉搜索树的每个节点,
- 如果该节点的值在
[low, high]范围内,那么,- 当前节点的左子树的节点都小于
high,所以要找到左子树中大于low的节点。 - 当前节点的右子树的节点都大于
low,所以要找到右子树中小于high的节点。
- 当前节点的左子树的节点都小于
- 如果该节点的值大于
low,那么当前节点和它左子树的所有节点的值都小于low,不符合条件;满足条件的值只会出现它的右子树,返回递归遍历右子树后的结果。 - 否则,该节点的值小于
hign,当前节点和它右子树的所有节点的值都大于high,不符合条件;满足条件的值只会出现它的左子树,返回递归遍历左子树后的结果。
代码
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public TreeNode trimBST(TreeNode root, int low, int high) {
if(root == null){
return null;
}
// 对于一个满足条件的节点 root ,
// 左子树 = 大于 low 的节点
// 右子树 = 小于 high 的节点
if(root.val >= low && root.val <= high){
root.left = trimBST(root.left,low,high);
root.right = trimBST(root.right,low,high);
return root;
}
// 如果 当前节点小于low, 那么满足条件的值只可能出现在右子树
if(root.val < low){
return trimBST(root.right,low,high);
}
// 当前节点大于 high , 满足条件的值只可能出现在左子树
return trimBST(root.left,low,high);
}
}
108.将有序数组转换为二叉搜索树
给你一个整数数组
nums,其中元素已经按 升序 排列,请你将其转换为一棵 高度平衡 二叉搜索树。
高度平衡 二叉树是一棵满足「每个节点的左右两个子树的高度差的绝对值不超过 1 」的二叉树。
108. 将有序数组转换为二叉搜索树 - 力扣(Leetcode)
思路
在有序数组中,每次取最中间的元素作为当前节点的值,并以此元素将当前区间分成左右两部分,作为当前节点的左右子树,这样,左右子树的节点数相等(或相差1,如果当前数组元素为偶数),满足平衡的要求;再分别对左子树和右子树递归进行,最终得到一棵平衡的二叉搜索树。
代码
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public TreeNode sortedArrayToBST(int[] nums) {
return traversal(nums, 0, nums.length - 1);
}
// 使用左闭右闭区间
// [left, right]
private TreeNode traversal(int nums[], int left, int right){
if(left > right){
return null;
}
// 中间下标
// 自动向下取整
int middle = (left + right) / 2;
TreeNode node = new TreeNode(nums[middle]);
node.left = traversal(nums, left, middle - 1);
node.right = traversal(nums, middle + 1, right);
return node;
}
}
538.把二叉搜索树转换为累加树
给出二叉 搜索 树的根节点,该树的节点值各不相同,请你将其转换为累加树(Greater Sum Tree),使每个节点
node的新值等于原树中大于或等于node.val的值之和。
538. 把二叉搜索树转换为累加树 - 力扣(Leetcode)
思路
累加树让每个节点 node 的新值等于原树中大于或等于 node.val 的值之和,那么二叉树中值最大的节点的新值就是它本身,任意比该值小的节点都要加上这个值。
在二叉搜索树的任一棵子树中,当前节点为node,根据二叉搜索树的定义,node.right.val > node.val > node.left.val 成立。因此遍历的顺序是右子树、中间节点、左子树,即右中左的遍历方式。
遍历完一个节点后,将该节点的新值返回,并作为参数传到下一个要遍历的节点。
代码
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public TreeNode convertBST(TreeNode root) {
traversal(root, 0);
return root;
}
// 右中左的遍历方式
private int traversal(TreeNode node, int sum){
if(node == null){
return sum;
}
// 右
int sumRight = traversal(node.right,sum);
// 中
node.val = node.val + sumRight;
int sumLeft = traversal(node.left, node.val);
return sumLeft;
}
}