Given the root of a binary search tree (BST), you are asked to transform the tree into a Greater Sum Tree (GST). In the resulting tree, every node's value is replaced by the sum of all values greater than or equal to that node's value in the original BST.
Formally, for each node with value val
in the BST, its new value should be the sum of all node values in the BST that are greater than or equal to val
.
Constraints:
To solve this problem, let's first consider what it means to replace each node with the sum of all greater or equal values. In a BST, an in-order traversal (left-root-right) gives us nodes in ascending order, but we want to accumulate from the largest to the smallest. This suggests we should traverse the tree in reverse in-order (right-root-left).
A brute-force approach might be, for each node, to search the entire tree and sum all values greater or equal to it. However, this would be very inefficient, especially for large trees.
Instead, we can use the BST properties to visit nodes in descending order and keep a running sum as we go, updating each node's value in-place. This avoids redundant work and leverages the sorted nature of the BST.
Here's how we can efficiently transform the BST to a Greater Sum Tree:
total
) to keep track of the sum of all nodes visited so far.
total
, then set the node's value to total
.
This approach leverages the BST's ordering, so each node is visited only once, and the running sum ensures we always know the sum of all greater or equal values.
Let's walk through an example with a simple BST:
4 / \ 1 6 / \ 5 7
total = 0
.total += 7 → total = 7
. Set 7's value to 7.
total += 6 → total = 13
. Set 6's value to 13.
total += 5 → total = 18
. Set 5's value to 18.
total += 4 → total = 22
. Set 4's value to 22.
total += 1 → total = 23
. Set 1's value to 23.
The final GST is:
22 / \ 23 13 / \ 18 7
By leveraging the properties of a binary search tree and using a reverse in-order traversal, we can efficiently compute the Greater Sum Tree in a single pass. The key insight is to accumulate a running sum as we visit nodes from largest to smallest, updating each node in-place. This avoids redundant computation and makes the solution both elegant and efficient.
# Definition for a binary tree node.
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
class Solution:
def bstToGst(self, root: TreeNode) -> TreeNode:
self.total = 0
def reverse_inorder(node):
if not node:
return
reverse_inorder(node.right)
self.total += node.val
node.val = self.total
reverse_inorder(node.left)
reverse_inorder(root)
return root
// Definition for a binary tree node.
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};
class Solution {
public:
int total = 0;
TreeNode* bstToGst(TreeNode* root) {
reverseInorder(root);
return root;
}
void reverseInorder(TreeNode* node) {
if (!node) return;
reverseInorder(node->right);
total += node->val;
node->val = total;
reverseInorder(node->left);
}
};
// Definition for a binary tree node.
class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
class Solution {
private int total = 0;
public TreeNode bstToGst(TreeNode root) {
reverseInorder(root);
return root;
}
private void reverseInorder(TreeNode node) {
if (node == null) return;
reverseInorder(node.right);
total += node.val;
node.val = total;
reverseInorder(node.left);
}
}
/**
* Definition for a binary tree node.
* function TreeNode(val, left, right) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
*/
/**
* @param {TreeNode} root
* @return {TreeNode}
*/
var bstToGst = function(root) {
let total = 0;
function reverseInorder(node) {
if (!node) return;
reverseInorder(node.right);
total += node.val;
node.val = total;
reverseInorder(node.left);
}
reverseInorder(root);
return root;
};