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.
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.
Each node should become the sum of all keys not smaller than itself. In a BST those keys are exactly the nodes already seen in reverse inorder.
Walk right-root-left, accumulate into \(s\), and write \(s\) back. The right subtree is processed first, so larger keys are already included. One traversal.
1 2 3 4 5 6 7 8 91011121314151617181920
# 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 = rightclassSolution:defconvertBST(self,root:TreeNode)->TreeNode:defdfs(root):nonlocalsifrootisNone:returndfs(root.right)s+=root.valroot.val=sdfs(root.left)s=0dfs(root)returnroot
/** * Definition for a binary tree node. * type TreeNode struct { * Val int * Left *TreeNode * Right *TreeNode * } */funcconvertBST(root*TreeNode)*TreeNode{s:=0vardfsfunc(*TreeNode)dfs=func(root*TreeNode){ifroot==nil{return}dfs(root.Right)s+=root.Valroot.Val=sdfs(root.Left)}dfs(root)returnroot}
Recursive reverse inorder uses an \(O(h)\) stack. Morris temporarily links a node's inorder predecessor (leftmost of the right subtree) to recover the parent without a stack.
Thread when going right, accumulate and write on the return visit, then unthread and go left. The order is still right-root-left, with constant extra space.
/** * Definition for a binary tree node. * type TreeNode struct { * Val int * Left *TreeNode * Right *TreeNode * } */funcconvertBST(root*TreeNode)*TreeNode{s:=0node:=rootforroot!=nil{ifroot.Right==nil{s+=root.Valroot.Val=sroot=root.Left}else{next:=root.Rightfornext.Left!=nil&&next.Left!=root{next=next.Left}ifnext.Left==nil{next.Left=rootroot=root.Right}else{s+=root.Valroot.Val=snext.Left=nilroot=root.Left}}}returnnode}
Solution 3: Explicit Stack
Thinking
Each node should become the sum of every key not smaller than itself. In a BST those keys are exactly the nodes already seen in reverse inorder. Recursing down the right child and writing the sum back is correct on a short tree.
The tree can contain \(10^4\) nodes. A right chain makes this walk recurse once per node and overflow the call stack.
The running sum depends only on the greater keys already visited. A node does not need a value returned from its children, as long as the right child is finished before the node and the left child comes after.
An explicit stack performs that reverse inorder. On entry it pushes an exit marker and the right child; on exit it adds the node value into \(s\), writes \(s\) back, and pushes the left child.
An explicit stack walks the binary search tree in the order right, root, left. On entry we push an exit marker and the right child. On exit we add the node value into \(s\), write \(s\) back to the node, and push the left child.
The time complexity is \(O(n)\), and the space complexity is \(O(n)\), where \(n\) is the number of nodes in the binary search tree.
1 2 3 4 5 6 7 8 910111213141516171819202122
# 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 = rightclassSolution:defconvertBST(self,root:TreeNode)->TreeNode:s=0stk=[(root,0)]whilestk:node,state=stk.pop()ifnodeisNone:continueifstate==0:stk.append((node,1))stk.append((node.right,0))continues+=node.valnode.val=sstk.append((node.left,0))returnroot
/** * Definition for a binary tree node. * type TreeNode struct { * Val int * Left *TreeNode * Right *TreeNode * } */funcconvertBST(root*TreeNode)*TreeNode{s:=0typeframestruct{node*TreeNodestateint}stk:=[]frame{{root,0}}forlen(stk)>0{cur:=stk[len(stk)-1]stk=stk[:len(stk)-1]node,state:=cur.node,cur.stateifnode==nil{continue}ifstate==0{stk=append(stk,frame{node,1},frame{node.Right,0})continue}s+=node.Valnode.Val=sstk=append(stk,frame{node.Left,0})}returnroot}