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
),以此类推。
参考: