题目
https://leetcode-cn.com/problems/convert-bst-to-greater-tree/
方法一:反中序遍历
分析
二叉搜索树的特点是:非叶子节点的元素大于它的左子树,小于它的右子树。
本题要求大于等于节点元素的和,所以遍历顺序是:右子树、根节点、左子树。
代码
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
int count=0;
public TreeNode convertBST(TreeNode root) {
dfs(root);
return root;
}
public void dfs(TreeNode root){
if(root==null){
return;
}
dfs(root.right);
root.val=root.val+count;
count=root.val;
dfs(root.left);
}
}
复杂度
时间复杂度:O(n),其中 n 是二叉搜索树的节点数。每一个节点恰好被遍历一次。
空间复杂度:O(n),为递归过程中栈的开销,平均情况下为O(logn),最坏情况下树呈现链状,为 O(n)。
结果
方法二:
分析
复杂度
时间复杂度:O(n),其中 nn 是二叉搜索树的节点数。没有左子树的节点只被访问一次,有左子树的节点被访问两次。
空间复杂度:O(1)。只操作已经存在的指针(树的空闲指针),因此只需要常数的额外空间。
代码
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public TreeNode convertBST(TreeNode root) {
TreeNode node=root;
int sum=0;
while(node!=null){
//右子树为空,计算当前节点值
if(node.right==null){
sum+=node.val;
node.val=sum;
node=node.left;
}
//右子树不为空
else{
//找到右子树的最左节点
TreeNode left=getSuccessor(node);
//是最左节点,最左节点left是当前节点node的前驱节点,设置一下,然后开始访问右子树
if(left.left==null){
left.left=node;
node=node.right;
}
//是当前节点,说明当前节点右子树已经访问完了
//恢复。计算当前节点值,访问当前节点左子树
else{
left.left=null;
sum+=node.val;
node.val=sum;
node=node.left;
}
}
}
return root;
}
//获取node的右子树的最左节点
public TreeNode getSuccessor(TreeNode node) {
TreeNode s=node.right;
while(s.left!=null&&s.left!=node){
s=s.left;
}
return s;
}
}