538. 把二叉搜索树转换为累加树
给定一个二叉搜索树(Binary Search Tree),把它转换成为累加树(Greater Tree),使得每个节点的值是原来的节点值加上所有大于它的节点值之和。例如:
输入: 原始二叉搜索树:
5
/ \
2 13
输出: 转换为累加树:
18
/ \
20 13
思路:
逆序中序遍历树即可,即按右-根-左的顺序遍历树
算法实现有两种方式,一种是递归方式,一种是非递归方式
递归方式
1 class Solution {
2 // 递归中序遍历
3 public TreeNode convertBST(TreeNode root) {
4 inTraversal(root);
5 return root;
6 }
7 public int sum = 0; // 共享单元
8
9 // 逆序中序遍历,右-根-左
10 public void inTraversal(TreeNode root){
11 if(root != null){
12 inTraversal(root.right);
13 sum += root.val;
14 root.val = sum;
15 inTraversal(root.left);
16 }
17 }
18
19 }
力扣测试时间为1ms, 空间为39.8MB
复杂度分析:
时间复杂度:对树的所有结点进行了一次遍历,所以时间复杂度为O(n)
空间复杂度:当树严重不平衡时,退化成链表,此时递归的最大层数为O(n), 所以空间复杂度为O(n)
其实可以不借助辅助函数
1 class Solution {
2 public int sum = 0;
3 public TreeNode convertBST(TreeNode root) {
4 // 递归中序遍历
5 if(root != null){
6 convertBST(root.right); // 把右子树转换成累加树
7 sum += root.val;
8 root.val = sum; // 当前结点累加上右子树的和
9 convertBST(root.left); // 把左子树转换成累加树
10 }
11 return root;
12 }
13 }
非递归方式:借用栈
1 class Solution {
2 // 递归中序遍历
3 public TreeNode convertBST(TreeNode root) {
4 int sum = 0;
5 Stack<TreeNode> stack = new Stack<TreeNode>();
6 TreeNode top = root;
7 while(!stack.empty() || top != null){
8 while(top != null){
9 stack.push(top);
10 top = top.right;
11 }
12 // 弹出栈顶元素进行访问
13 top = stack.pop();
14 top.val += sum;
15 sum = top.val;
16 top = top.left;
17 }
18 return root;
19 }
20 }
力扣测试时间为:3ms, 空间为39.9MB
复杂度分析
复杂度分析:对树的所有结点进行了一次遍历,所以时间复杂度为O(n)
时间复杂度:空间花费就是栈的大小,当树严重不平衡时,退化成链表,此时栈的最大大小为n, 所以空间复杂度为O(n)
从测试结果来看,递归方式比非递归方式要快一些