问题
给出二叉搜索树的根节点,该树的节点值各不相同,请你将其转换为累加树(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]
解法一:递归
反中序遍历二叉搜索树,记录过程中的节点值之和,顺序累加,并不断更新当前遍历到的节点的节点值
class Solution {
int sum = 0;
public TreeNode convertBST(TreeNode root) {
if(root != null){
convertBST(root.right);
sum += root.val;
root.val = sum;
convertBST(root.left);
}
return root;
}
}
- 时间复杂度:
,其中
n
是二叉搜索树的节点数。每一个节点恰好被遍历一次 - 空间复杂度:
,为递归过程中栈的开销,平均情况下为
,最坏情况下树呈现链状,为
可以通过一个pre
指针记录当前遍历节点cur
的前一个结点
递归函数参数以及返回值
- 不需要返回值
- 定义一个全局变量
pre
,用于保存cur
节点的前一个节点的数值int pre;
void traversal(TreeNode cur);
确定终止条件
if(cur == null) return null;
确定单层递归逻辑
右中左来遍历二叉树,中节点的处理逻辑就是让
cur
加上前一个节点的数值traversal(cur.right);
cur.val += pre;
pre = cur.val;
traversal(cur.left);
class Solution {
int pre; // 记录前一个节点的数值
void traversal(TreeNode cur) { // 右中左遍历
if (cur == null) return;
traversal(cur.right);
cur.val += pre;
pre = cur.val;
traversal(cur.left);
}
public TreeNode convertBST(TreeNode root) {
pre = 0;
traversal(root);
return root;
}
}
解法二:迭代
class Solution {
int pre; // 记录前一个节点的数值
public void traversal(TreeNode root) {
Deque<TreeNode> st = new LinkedList<TreeNode>();
TreeNode cur = root;
while (cur != null || !st.isEmpty()) {
if (cur != null) {
st.push(cur);
cur = cur.right; // 右
} else {
cur = st.pop(); // 中
cur.val += pre;
pre = cur.val;
cur = cur.left; // 左
}
}
}
public TreeNode convertBST(TreeNode root) {
pre = 0;
traversal(root);
return root;
}
}