Problem
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 the sum of all keys greater than the original key in BST.
Examples
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]
Solution
Method 1 - Brute Force
Naive approach will be for every node, traverse the tree and find out all the nodes which are greater and update the node. But the time complexity of this approach will be O(n^2)
.
Method 2 - Recursive Reverse Inorder Traversal
Since this is a BST, the right most node in the BST is the biggest node among all the nodes. So, we can start from right, i.e. we do a reverse inorder traversal to traverse the nodes of the tree in descending order. Since we are visiting the nodes in the decreasing order, all we care about is maintaining the running sum of the nodes visited thus far.
In the process, we keep track of the running sum of all nodes which we have traversed thus far.
Here is the video explanation:
Code
Java
Using global variables
public class Solution {
private int sum = 0;
public TreeNode bstToGst(TreeNode root) {
if (root == null) {
return null;
}
bstToGst(root.right); //visit the right node first
sum += root.val; //update the sum for the next node
root.val = sum;
bstToGst(root.left);
return root;
}
}
Without using global variables with object
class Solution {
public TreeNode bstToGst(TreeNode root) {
reverseInorder(root, new TreeNode(0));
return root;
}
private void reverseInorder(TreeNode root, TreeNode sum) {
if (root == null) {
return;
}
int right = reverseInorder(root.right, sum);
sum.val += root.val;
root.val = sum.val;
return reverseInorder(root.left, sum);
}
}
Without using global variables with primitive
We can also just passed the primitive sum, but return int in reverseInorder()
method.
class Solution {
public TreeNode bstToGst(TreeNode root) {
reverseInorder(root, 0);
return root;
}
private int reverseInorder(TreeNode root, int sum) {
if (root == null) {
return sum;
}
int right = reverseInorder(root.right, sum); // pass in provided sum for accumulation
root.val = root.val + right;
return reverseInorder(root.left, root.val); // pass in updated sum
}
}
Complexity
- ⏰ Time complexity:
O(n)
, where n is number of nodes in tree. - 🧺 Space complexity:
O(n)
for using recursive stack
Method 4 - Iterative Reverse Inorder Traversal
Initially, use curr
to point to the root,
- push into Stack the right-most path of current subtree;
- pop out a node, update sum and the node value;
- point
curr
to the node’s left child, if any; Repeat the above till the stack is empty andcurr
has no left child.
Code
Java
class Solution {
public TreeNode bstToGst(TreeNode root) {
Deque<TreeNode> stk = new ArrayDeque<>();
TreeNode curr = root;
int sum = 0;
while (curr != null || !stk.isEmpty()) {
while (curr != null) { // save right-most path of the current subtree
stk.push(curr);
curr = curr.right;
}
curr = stk.pop(); // pop out by reversed in-order.
sum += curr.val; // update sum.
curr.val = sum; // update node value.
curr = curr.left; // move to left branch.
}
return root;
}
}
Complexity
- ⏰ Time complexity:
O(n)
, where n is number of nodes in tree. - 🧺 Space complexity:
O(n)
for using stack