LeetCode—538. 把二叉搜索树转换为累加树[Convert BST to Greater Tree]——分析及代码[Java]
一、题目
给出二叉搜索树的根节点,该树的节点值各不相同,请你将其转换为累加树(Greater Sum Tree),使每个节点 node 的新值等于原树中大于或等于 node.val 的值之和。
提醒一下,二叉搜索树满足下列约束条件:
- 节点的左子树仅包含键 小于 节点键的节点。
- 节点的右子树仅包含键 大于 节点键的节点。
- 左右子树也必须是二叉搜索树。
注意:本题和 1038: https://leetcode-cn.com/problems/binary-search-tree-to-greater-sum-tree/ 相同
示例 1:
输入:[4,1,6,0,2,5,7,null,null,null,3,null,null,null,8]
输出:[30,36,21,36,35,26,15,null,null,null,33,null,null,null,8]
示例 2:
输入:root = [0,null,1]
输出:[1,null,1]
示例 3:
输入:root = [1,0,2]
输出:[3,3,2]
示例 4:
输入:root = [3,2,4,1]
输出:[7,9,4,10]
提示:
- 树中的节点数介于 0 和 104 之间。
- 每个节点的值介于 -104 和 104 之间。
- 树中的所有值 互不相同 。
- 给定的树为二叉搜索树。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/convert-bst-to-greater-tree
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
二、分析及代码
1. 反向中序遍历
(1)思路
结合二叉搜索树的特点,从右至左反向进行中序遍历的同时累加,即可将其转换为所需的累加树。
(2)代码(迭代)
import java.util.Stack;
class Solution {
public TreeNode convertBST(TreeNode root) {
if (root == null)
return root;
int sum = 0;
Stack<TreeNode> sta = new Stack<>();
sta.push(root);
while (!sta.empty()) {
TreeNode node = sta.pop();
while (node.right != null) {
sta.push(node);
node = node.right;
}
while (!sta.empty() && node.left == null) {
node.val += sum;
sum = node.val;
node = sta.pop();
}
node.val += sum;
sum = node.val;
if (node.left != null)
sta.push(node.left);
}
return root;
}
}
(3)结果(迭代)
执行用时 :2 ms, 在所有 Java 提交中击败了 14.93% 的用户;
内存消耗 :39 MB, 在所有 Java 提交中击败了 42.05% 的用户。
(4)代码(递归)
import java.util.Stack;
class Solution {
int sum = 0;
public TreeNode convertBST(TreeNode root) {
if (root == null)
return root;
convertBST(root.right);
root.val += sum;
sum = root.val;
convertBST(root.left);
return root;
}
}
(5)结果(递归)
执行用时 :1 ms, 在所有 Java 提交中击败了 97.46% 的用户;
内存消耗 :38.9 MB, 在所有 Java 提交中击败了 80.46% 的用户。
2. Morris 遍历
(1)思路
可结合 Morris 方法,对遍历过程进一步优化,通过利用树中的空闲指针,在常数空间和线性时间内完成遍历,其过程为:
- 若右节点为空,处理当前节点,并跳转到其左节点;
- 若右节点的最左子节点的左节点为空,将最左子节点的左节点设置为当前节点,并跳转到其右节点;
- 若右节点的最左子节点的左节点为当前节点,将最左子节点的左节点设置为空,处理当前节点,并跳转到其左节点。
(2)代码
class Solution {
public TreeNode convertBST(TreeNode root) {
int sum = 0;
TreeNode node = root;
while (node != null) {
if (node.right == null) {
node.val += sum;
sum = node.val;
node = node.left;
} else {
TreeNode succ = getSucc(node);
if (succ.left == null) {
succ.left = node;
node = node.right;
} else {
succ.left = null;
node.val += sum;
sum = node.val;
node= node.left;
}
}
}
return root;
}
private TreeNode getSucc(TreeNode node) {
TreeNode succ = node.right;
while (succ.left != null && succ.left != node)
succ = succ.left;
return succ;
}
}
(3)结果
执行用时 :1 ms, 在所有 Java 提交中击败了 96.43% 的用户;
内存消耗 :38.7 MB, 在所有 Java 提交中击败了 92.72% 的用户。
三、其他
暂无。