把二叉搜索树转换为累加树 - 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遍历算法的步骤:

  1. 根据当前节点,找到其前序节点,如果前序节点的右孩子是空,那么把前序节点的右孩子指向当前节点,然后进入当前节点的左孩子。
  2. 如果当前节点的左孩子为空,打印当前节点,然后进入右孩子。
  3. 如果当前节点的前序节点其右孩子指向了它本身,那么把前序节点的右孩子设置为空,打印当前节点,然后进入右孩子。


相关阅读:算法数据结构,如何面试进入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),以此类推。

参考:

posted @ 2020-12-22 16:49  gzhjj  阅读(99)  评论(0编辑  收藏  举报