[LeetCode] 538. Convert BST to Greater Tree 将二叉搜索树BST转为较大树
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<TreeNode*> 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