一、力扣题669. 修剪二叉搜索树
给你二叉搜索树的根节点 root ,同时给定最小边界low 和最大边界 high。通过修剪二叉搜索树,使得所有节点的值在[low, high]中。修剪树 不应该 改变保留在树中的元素的相对结构 (即,如果没有被移除,原有的父代子代关系都应当保留)。 可以证明,存在 唯一的答案 。
所以结果应当返回修剪好的二叉搜索树的新的根节点。注意,根节点可能会根据给定的边界发生改变。
示例 1:

输入:root = [1,0,2], low = 1, high = 2 输出:[1,null,2]
示例 2:

输入:root = [3,0,4,null,2,null,null,1], low = 1, high = 3 输出:[3,2,null,1]
提示:
- 树中节点数在范围
[1, 104]内 0 <= Node.val <= 104- 树中每个节点的值都是 唯一 的
- 题目数据保证输入是一棵有效的二叉搜索树
0 <= low <= high <= 104
这道题同样是涉及改变二叉树结构的,先列举一下有哪些情况,已知最小边界为 low,最大边界为 high。 当一个节点值在 [ low, high ] 区间之外说明该节点需要被删除,但该节点的子节点又可能符合 [ low,high] 区间,比如例2,所以不能直接删除这个节点及其子节点,只能删除该节点并让子节点补位。
以下列举情况:
1、节点在 [ low, high ] 区间内,继续遍历其左右节点。
2、节点为空,返回 null。
3、节点值小于 low,说明该节点的左子树全都不符合条件,所以直接让其右节点取代该节点,并继续递归右节点。
4、节点值大于 high,说明该节点的右子树全都不符合条件,直接让左节点取代该节点,继续递归左节点。
情况列举清楚了,如何处理被删除节点的子节点也就清楚了。接下来就只剩一个问题,如何让子节点取代被删除的节点,明显是用 $root -> left 或者 $root -> right 来指向递归左右节点后返回的值,如果递归的左节点要被删除,返回的就不是左节点,而是左节点的子节点,那么 $root -> left 指向的就是左节点的子节点,这样自然而然地就删除了左节点。
这种处理方式比较难想到,要努力熟悉这种应用,某种程度上这种也是一种自下而上的逻辑。
function trimBST($root, $low, $high) {
if($root === null) return null;
if($root->val > $high) {
return $this->trimBST($root->left, $low, $high);
}
if($root->val < $low) {
return $this->trimBST($root->right, $low, $high);
}
$root->left = $this->trimBST($root->left, $low, $high);
$root->right = $this->trimBST($root->right, $low, $high);
return $root;
}
二、力扣题108. 将有序数组转换为二叉搜索树
给你一个整数数组 nums ,其中元素已经按 升序 排列,请你将其转换为一棵 高度平衡 二叉搜索树。
高度平衡 二叉树是一棵满足「每个节点的左右两个子树的高度差的绝对值不超过 1 」的二叉树。
示例 1:

输入:nums = [-10,-3,0,5,9] 输出:[0,-3,9,-10,null,5] 解释:[0,-10,5,null,-3,null,9] 也将被视为正确答案:

示例 2:

输入:nums = [1,3] 输出:[3,1] 解释:[1,null,3] 和 [3,1] 都是高度平衡二叉搜索树。
提示:
1 <= nums.length <= 104-104 <= nums[i] <= 104nums按 严格递增 顺序排列
这道题和之前的 “用前序和后序序列构造二叉树” 有点像,都是要先充分了解构造过程,再来填入递归的逻辑中。
将一个升序数组转化为二叉搜索树,并且要求是高度平衡的二叉搜索树,即每个节点的左右子树高度差不能超过1。
那么每次取中节点时,都要取数组最中间的值,这样中节点两边的数组个数的绝对差才能不超过1。
递归参数:数组; 终止条件:数组为空;返回参数:构造的中节点。
单层递归逻辑:获取数组最中间的值,将该值赋给一个新节点 cur ,将这个值左右两边的数组都切割出来,cur -> left 和 cur -> right 分别存放递归这两个左右数组返回的值,返回节点 cur。
function sortedArrayToBST($nums) {
if($nums == []) return null;
$sub = intval(count($nums) / 2);
$cur = new TreeNode($nums[$sub]);
$cur->left = $this->sortedArrayToBST(array_slice($nums, 0, $sub));
$cur->right = $this->sortedArrayToBST(array_slice($nums, $sub + 1));
return $cur;
}
三、力扣题538. 把二叉搜索树转换为累加树
给出二叉 搜索 树的根节点,该树的节点值各不相同,请你将其转换为累加树(Greater Sum Tree),使每个节点 node 的新值等于原树中大于或等于 node.val 的值之和。
提醒一下,二叉搜索树满足下列约束条件:
- 节点的左子树仅包含键 小于 节点键的节点。
- 节点的右子树仅包含键 大于 节点键的节点。
- 左右子树也必须是二叉搜索树。
注意:本题和 1038: 力扣 相同
示例 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之间。 - 树中的所有值 互不相同 。
- 给定的树为二叉搜索树。
累加树的定义是:每个节点 node 的新值等于原树中大于或等于 node.val 的值之和。
而如果中序遍历二叉搜索树,遍历的节点的值一定是从小到大的,反过来用 “右中左” 的顺序遍历二叉搜索树,遍历的节点的值一定是从大到小的。
将按“右中左”顺序遍历节点的值先设定成一个降序数组,数组中的值如果要符合累加树的特性,那数组中的每个值都要加上这个值前面的所有值,比如 arr [3] = arr [0] + arr [1] + arr [2],这样来处理就简单多了。
递归参数:节点;终止条件:节点为空;无返回参数。
设置一个全局变量 sum 用于存放比当前节点大的所有节点值的总和。
单层递归逻辑:先递归当前节点的右节点,将 sum 的值加上当前节点的值,再把 sum 赋给当前节点,最后递归当前节点的左节点。
class Solution {
private $sum = 0;
/**
* @param TreeNode $root
* @return TreeNode
*/
function convertBST($root) {
if(!$root) return null;
$this->convert($root);
return $root;
}
function convert($root) {
if(!$root) return;
$this->convert($root->right);
$this->sum += $root->val;
$root->val = $this->sum;
$this->convert($root->left);
}
}
文章介绍了如何使用递归算法对二叉搜索树进行修剪,使其所有节点值位于特定范围内,以及如何将有序数组转换为高度平衡的二叉搜索树。此外,还讲解了如何将二叉搜索树转换为累加树,使每个节点值等于大于或等于其值的节点之和。
984

被折叠的 条评论
为什么被折叠?



