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.
Traverse the binary search tree in the order of "right-root-left". Accumulate all the node values encountered into \(s\), and assign the accumulated value to the corresponding node.
Time complexity is \(O(n)\), and 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 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:defbstToGst(self,root:Optional[TreeNode])->Optional[TreeNode]:defdfs(root:Optional[TreeNode]):ifrootisNone:returndfs(root.right)nonlocalss+=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 * } */funcbstToGst(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}
/** * Definition for a binary tree node. * struct TreeNode { * int val; * struct TreeNode *left; * struct TreeNode *right; * }; */intdfs(structTreeNode*root,intsum){if(root){sum=dfs(root->right,sum)+root->val;root->val=sum;sum=dfs(root->left,sum);}returnsum;}structTreeNode*bstToGst(structTreeNode*root){dfs(root,0);returnroot;}
Solution 2: Morris Traversal
Morris traversal does not require a stack, with a time complexity of \(O(n)\) and a space complexity of \(O(1)\). The core idea is as follows:
Define \(s\) as the cumulative sum of the node values in the binary search tree. Traverse the binary tree nodes:
If the right subtree of the current node root is null, add the current node value to \(s\), update the current node value to \(s\), and move the current node to root.left.
If the right subtree of the current node root is not null, find the leftmost node next in the right subtree (i.e., the successor node of root in an in-order traversal):
If the left subtree of the successor node next is null, set the left subtree of next to point to the current node root, and move the current node to root.right.
If the left subtree of the successor node next is not null, add the current node value to \(s\), update the current node value to \(s\), then set the left subtree of next to null (i.e., remove the link between next and root), and move the current node to root.left.
Repeat the above steps until the binary tree nodes are null, at which point the traversal is complete.
Finally, return the root node of the binary search tree.
Morris reverse in-order traversal follows the same idea as Morris in-order traversal, except that the traversal order changes from "left-root-right" to "right-root-left".
/** * Definition for a binary tree node. * type TreeNode struct { * Val int * Left *TreeNode * Right *TreeNode * } */funcbstToGst(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}