Given the root of a Binary Search Tree (BST), convert it to a Greater Tree such that every key of the original BST is changed to the original key plus sum of all keys greater than the original key in BST.

As a reminder, a binary search tree is a tree that satisfies these constraints:

The left subtree of a node contains only nodes with keys less than the node's key.

The right subtree of a node contains only nodes with keys greater than the node's key.

Both the left and right subtrees must also be binary search trees.

Note: This question is the same as 1038: https://leetcode.com/problems/binary-search-tree-to-greater-sum-tree/

 

Example 1:

Input: root = [4,1,6,0,2,5,7,null,null,null,3,null,null,null,8]

Output: [30,36,21,36,35,26,15,null,null,null,33,null,null,null,8]

Example 2:

Input: root = [0,null,1]

Output: [1,null,1]

Example 3:

Input: root = [1,0,2]

Output: [3,3,2]

Example 4:

Input: root = [3,2,4,1]

Output: [7,9,4,10]

 

Constraints:

The number of nodes in the tree is in the range [0, 104].

-104 <= Node.val <= 104

All the values in the tree are unique.

root is guaranteed to be a valid binary search tree.

 

这道题让我们将二叉搜索树转为较大树,通过题目汇总的例子可以明白,是把每个结点值加上所有比它大的结点值总和当作新的结点值。仔细观察题目中的例子可以发现,2变成了 20,而 20 是所有结点之和,因为2是最小结点值,要加上其他所有结点值,所以肯定就是所有结点值之和。5变成了 18,是通过 20 减去2得来的,而 13 还是 13,是由 20 减去7得来的,而7是2和5之和。博主开始想的方法是先求出所有结点值之和,然后开始中序遍历数组,同时用变量 sum 来记录累加和,根据上面分析的规律来更新所有的数组。但是通过看论坛,发现还有更巧妙的方法,不用先求出的所有的结点值之和,而是巧妙的将中序遍历左根右的顺序逆过来,变成右根左的顺序,这样就可以反向计算累加和 sum,同时更新结点值,叼的不行,参见代码如下:

 

解法一:

class Solution {

public:

TreeNode* convertBST(TreeNode* root) {

int sum = 0;

helper(root, sum);

return root;

}

void helper(TreeNode*& node, int& sum) {

if (!node) return;

helper(node->right, sum);

node->val += sum;

sum = node->val;

helper(node->left, sum);

}

};

 

下面这种方法写的更加简洁一些,没有写其他递归函数,而是把自身写成了可以递归调用的函数,参见代码如下:

 

解法二:

class Solution {

public:

TreeNode* convertBST(TreeNode* root) {

if (!root) return NULL;

convertBST(root->right);

root->val += sum;

sum = root->val;

convertBST(root->left);

return root;

}

private:

int sum = 0;

};

 

下面这种解法是迭代的写法,因为中序遍历有递归和迭代两种写法,逆中序遍历同样也可以写成迭代的形式,参加代码如下:

 

解法三:

class Solution {

public:

TreeNode* convertBST(TreeNode* root) {

if (!root) return NULL;

int sum = 0;

stack st;

TreeNode *p = root;

while (p || !st.empty()) {

while (p) {

st.push(p);

p = p->right;

}

p = st.top(); st.pop();

p->val += sum;

sum = p->val;

p = p->left;

}

return root;

}

};

 

Github 同步地址:

https://github.com/grandyang/leetcode/issues/538

 

参考资料:

https://leetcode.com/problems/convert-bst-to-greater-tree/

https://leetcode.com/problems/convert-bst-to-greater-tree/discuss/100506/Java-Recursive-O(n)-time

https://leetcode.com/problems/convert-bst-to-greater-tree/discuss/100610/c%2B%2B-solution-beats-100

 

LeetCode All in One 题目讲解汇总(持续更新中...)

查看原文