题目
中等
相关标签
给出二叉 搜索 树的根节点,该树的节点值各不相同,请你将其转换为累加树(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
之间。 - 树中的所有值 互不相同 。
- 给定的树为二叉搜索树。
思路和解题方法
- 首先,我们定义一个
pre
变量并将其初始化为0,用于保存前缀和。- 然后,我们定义一个
traversal
函数来遍历树。如果当前节点为空,则返回。否则,我们按照右子树、当前节点、左子树的顺序递归调用traversal
函数。- 在遍历右子树之后,我们将当前节点的值与
pre
相加,并将结果赋给当前节点的值。这样做后,当前节点的值就变成了大于等于它的所有节点值之和。- 接下来,我们更新
pre
的值为当前节点的值,以便在遍历左子树时使用。- 最后,我们递归调用
traversal
函数来遍历左子树。- 在
convertBST
函数中,我们调用traversal
函数对树进行反向中序遍历,并将修改后的根节点返回。
复杂度
时间复杂度:
O(n)
时间复杂度:O(n),其中 n 是二叉搜索树中的节点数量。因为我们需要遍历每个节点一次,所以时间复杂度是线性的。
空间复杂度
O(h)
空间复杂度:O(h),其中 h 是二叉搜索树的高度。在最坏情况下,如果树是完全不平衡的,即退化为链表,递归调用栈的深度将是 O(n)。但在平衡的情况下,二叉搜索树的高度是 O(logn),所以递归调用栈的深度是 O(logn),空间复杂度较低。
c++ 代码
class Solution {
public:
int pre = 0; // 前缀和初始化为0
// 反向中序遍历,将树上结点的值修改为大于等于它的所有值之和
void traversal(TreeNode *root)
{
if (root == NULL) return; // 遍历到叶子结点时返回
traversal(root->right); // 遍历右子树
root->val += pre; // 将当前结点的值加上前缀和
pre = root->val; // 更新前缀和
traversal(root->left); // 遍历左子树
}
TreeNode* convertBST(TreeNode* root) {
traversal(root); // 调用反向中序遍历函数
return root; // 返回修改后的根节点
}
};
c++迭代版本代码
class Solution {
private:
int pre; // 记录前一个节点的数值
void traversal(TreeNode* root) {
stack<TreeNode*> st;
TreeNode* cur = root;
while (cur != NULL || !st.empty()) {
if (cur != NULL) {
st.push(cur);
cur = cur->right; // 右子树
} else {
cur = st.top(); // 当前节点
st.pop();
cur->val += pre; // 处理当前节点
pre = cur->val; // 更新前缀和
cur = cur->left; // 左子树
}
}
}
public:
TreeNode* convertBST(TreeNode* root) {
pre = 0; // 初始化前缀和为0
traversal(root); // 对二叉搜索树进行反向中序遍历
return root; // 返回根节点
}
};
觉得有用的话可以点点赞,支持一下。
如果愿意的话关注一下。会对你有更多的帮助。
每天都会不定时更新哦 >人< 。