从二叉搜索树到更大和树
难度:
标签:
题目描述
给定一个二叉搜索树 root
(BST),请将它的每个节点的值替换成树中大于或者等于该节点值的所有节点值之和。
提醒一下, 二叉搜索树 满足下列约束条件:
- 节点的左子树仅包含键 小于 节点键的节点。
- 节点的右子树仅包含键 大于 节点键的节点。
- 左右子树也必须是二叉搜索树。
示例 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]
提示:
- 树中的节点数在
[1, 100]
范围内。 0 <= Node.val <= 100
- 树中的所有值均 不重复 。
注意:该题目与 538: https://leetcode-cn.com/problems/convert-bst-to-greater-tree/ 相同
代码结果
运行时间: 23 ms, 内存: 15.9 MB
/*
题目思路:
- 使用Stream API的方式来实现相同的逻辑。
- 由于Stream API主要用于操作集合类,通常不会直接处理树结构,因此,这里提供了一种模拟Stream API风格的代码。
*/
import java.util.ArrayList;
import java.util.List;
class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
public class Solution {
private int sum = 0;
public TreeNode convertBST(TreeNode root) {
List<TreeNode> list = new ArrayList<>();
traverseAndCollect(root, list);
list.stream().sorted((a, b) -> b.val - a.val).forEach(node -> {
sum += node.val;
node.val = sum;
});
return root;
}
private void traverseAndCollect(TreeNode node, List<TreeNode> list) {
if (node == null) return;
traverseAndCollect(node.left, list);
list.add(node);
traverseAndCollect(node.right, list);
}
}
解释
方法:
本题的解决方案基于二叉搜索树(BST)的特性,利用中序遍历的变体来解决问题。传统的中序遍历(左-中-右)可以访问BST中的节点,使节点值按升序排列。为了计算每个节点的新值,需要对所有大于或等于该节点值的节点值进行求和,可以通过反中序遍历(右-中-左)来实现,这样可以从最大的节点开始累加值。具体过程是:从BST的最右侧节点开始遍历,累计过程中将每个节点的值加到一个累积和中,并更新当前节点值为这个累积和。这种方式确保了每个节点在更新其值之前,所有大于该节点的值已被累加到总和中。
时间复杂度:
O(n)
空间复杂度:
O(h),其中 h 是树的高度
代码细节讲解
🦆
在你的解决方案中,为什么选择反中序遍历(右-中-左)而不是正中序遍历来更新节点值?
▷🦆
你提到了反中序遍历可以从最大的节点开始累加值,这个过程是否假设了树的结构总是对称或平衡?如果不是,这种方法的效率如何受到影响?
▷🦆
在代码中,`self.pre`变量是如何确保在递归调用中正确累加的?是否存在线程安全问题或者递归深度过深导致的堆栈溢出风险?
▷🦆
示例输出中,树节点的更新值是如何确保包含了所有大于等于该节点值的节点之和?是否有可能存在漏算的情况?
▷