把二叉搜索树转换为累加树 - Morris遍历
1. 题目描述
给出二叉搜索树的根节点,该树的节点值各不相同,请你将其转换为累加树(Greater Sum Tree),使每个节点node的新值等于原树中大于或等于node.val的值之和。
提醒一下,二叉搜索树满足下列约束条件:
- 节点的左子树仅包含键 小于 节点键的节点。
- 节点的右子树仅包含键 大于 节点键的节点。
- 左右子树也必须是二叉搜索树。
示例 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. 题解
Morris遍历算法的步骤:
- 根据当前节点,找到其前序节点,如果前序节点的右孩子是空,那么把前序节点的右孩子指向当前节点,然后进入当前节点的左孩子。
- 如果当前节点的左孩子为空,打印当前节点,然后进入右孩子。
- 如果当前节点的前序节点其右孩子指向了它本身,那么把前序节点的右孩子设置为空,打印当前节点,然后进入右孩子。

相关阅读:算法数据结构,如何面试进入google-51 二叉树的Morris遍历法 - YouTube
public TreeNode convertBST(TreeNode root) {
int sum = 0;
TreeNode node = root;
while (node != null) {
if (node.right == null) {
sum += node.val;
node.val = sum;
node = node.left;
} else {
TreeNode succ = getSuccessor(node); // 后继节点
if (succ.left == null) {
succ.left = node;
node = node.right;
} else {
succ.left = null;
sum += node.val;
node.val = sum;
node = node.left;
}
}
}
return root;
}
public TreeNode getSuccessor(TreeNode node) {
TreeNode succ = node.right;
while (succ.left != null && succ.left != node) {
succ = succ.left;
}
return succ;
}
Morris遍历的关键是找前序节点,而这里把二叉搜索树转换为累加树的关键是找后继节点,方法名getSuccessor中的successor是后继者的意思。
将当前节点的值加上后继节点的值作为当前节点的新值。
原来节点8(这里表示值为8的节点)没有后继节点,所以节点8的新值还是8。
原来节点7的后继节点为节点8(新值),于是节点7的新值为15(7 + 8);原来节点6的后继节点为节点15(新值),于是节点6的新值为21(6 + 15),以此类推。
参考:

浙公网安备 33010602011771号