从前序中序遍历序列构造二叉树的迭代算法理解

力扣上这道题的大神的迭代解法不是特别好理解,比如 详细通俗的思路分析,多解法 的迭代算法,看着解法新颖,但是我看了大半天都吃不透。后来想到了一个关于栈的算法题,就是给定两个数组 A 和 B,A 代表的是元素入栈的顺序,问 B 的元素顺序是不是 A 的出栈顺序。可以说,理解了出栈顺序这道题,基本就理解了这个二叉树构造的迭代算法了。

数组 A :[1,2,3,4,5],数组 B1 :[5,4,3,2,1],B2:[4,5,3,2,1],B3 :[3,4,5,2,1]。数组 B1,B2,B3 均是数组 A 的合法出栈顺序。我们可以发现,每次都是从 A 里面拿元素放入栈中,然后看栈顶元素值是不是和数组 B 指针指向的值相等,相等则弹出,否则不断将数组 A 的元素入栈。

而构造树,相对出栈顺序而言,要复杂一点,首先它是二维的,再一个就是任一节点都和根节点一样,也代表了一棵树,具有递归属性。

public static TreeNode build(int[] preArr, int[] inArr){
	if (preArr == null || inArr == null || preArr.length != inArr.length || inArr.length == 0)
		return null;
	int pre = 0, in = 0;
	TreeNode root = new TreeNode(preArr[pre++]), curRoot = root;
	Stack<TreeNode> s = new Stack<>();
	s.push(root);
	while (pre < preArr.length){
		if (s.peek().val == inArr[in]){
			while (!s.isEmpty() && s.peek().val == inArr[in]){
				curRoot = s.pop();
				in++;
			}
			curRoot.right = new TreeNode(preArr[pre++]);
			s.push(curRoot.right);
			curRoot = curRoot.right;
		} else {
			curRoot.left = new TreeNode(preArr[pre++]);
			s.push(curRoot.left);
			curRoot = curRoot.left;
		}
	}		
	return root;
}

我的理解如下:

1. while 不断遍历前序数组 (出栈题是遍历数组 A)
2. 每次都是先检查栈顶元素是不是等于中序指针指向的元素,然后根据情况入栈 (出栈题也是入栈前,检查栈顶元素是否
等于数组 B 指针指向的值)
	a. 不相等,说明前序数组指针指向的元素是栈顶元素的左子节点
	b. 相等,说明栈顶节点的左子树遍历完了或者为空
	c. 第二个 while 循环是针对某个节点子孙节点都没有右子树的情况
3. 出栈完了后,那么此时的前序元素是 curRoot 节点的右子节点 (出栈题是一维的,树是二维的,所以要用 curRoot 
维持状态,至于为什么是右子节点看文中链接作者给出的反证法)
4. curRoot 的右子节点也需要入栈,然后 curRoot 指向这个右子节点继续遍历
5. 此时,等于完成了一轮根节点的所有左子树节点入栈的过程,入栈和出栈过程中关联节点。当 curRoot 指向某个节点
的右子树节点时,此时的 curRoot 就和 root 性质一样了,逻辑上是“递归”以它为“根”节点的子树遍历过程

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值