【LeetCode算法修炼+动画演示】【二叉树的序列化】—— 105.从前序与中序遍历序列构造二叉树、106.从中序与后序遍历序列构造二叉树

1. 105.从前序与中序遍历序列构造二叉树

原题链接
根据一棵树的前序遍历与中序遍历构造二叉树。

注意:
你可以假设树中没有重复的元素。

例如,给出

前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]

返回如下的二叉树:

  3
 / \
9  20
  /  \
 15   7

1.1. 要点

  1. 前序遍历的过程中,每次最先遇到的都可以将其视为子树的根结点。
  2. 对比一下前序遍历的数组preorder,不难发现

    第一个数是二叉树的根结点
    第二个数是左子树的根结点
    第三个数是右子树的根结点
    依次类推…

  3. 知道这个特性之后,我们需要知道哪些元素应该在左边,哪些在右边。
  4. 你应该要能理解中序遍历inorder:根结点是在中间被遍历到的,也就是说在中序遍历过程中,根结点的左边数组为左子树元素而右边是右子树元素。
  5. 要做的事情就是确定根结点,之后确认子树的根结点。

    将有序数组转换为二叉搜索树动画演示

1.2. 递归

1.2.1. 代码片段

func buildTree(preorder []int, inorder []int) *TreeNode {
	if len(preorder) == 0 || len(inorder) == 0 {
		return nil
	}
	var num = 0
	return buildTreeHelper(preorder, inorder, &num)
}

func buildPos(inorder []int, val int) int {
	var pos int
	for i, v := range inorder {
		if v == val {
			pos = i
			break
		}
	}
	return pos
}

func buildTreeHelper(preorder []int, inorder []int, num *int) *TreeNode {
	val := preorder[*num]
	tree := &TreeNode{
		Val: val,
	}

	pos := buildPos(inorder, val)

	var left, right []int
	if pos-1 >= 0 {
		*num++
		left = inorder[:pos]
		tree.Left = buildTreeHelper(preorder, left, num)
	}
	if pos+1 < len(inorder) {
		*num++
		right = inorder[pos+1:]
		tree.Right = buildTreeHelper(preorder, right, num)
	}
	return tree
}
代码解释
  1. 每一次取出一个根结点并创建子树。
  2. 递归创建左右子树,注意 num是一个指针变量,因为在每一次递归过程中创建的节点都是唯一的,且每一次都是顺序往下拿,如果不是指针变量会导致重复创建结点。

2. 106.从中序与后序遍历序列构造二叉树

原题链接
根据一棵树的中序遍历与后序遍历构造二叉树。

注意:
你可以假设树中没有重复的元素。

例如,给出

中序遍历 inorder = [9,3,15,20,7]
后序遍历 postorder = [9,15,7,20,3]

返回如下的二叉树:

    3
   / \
  9  20
    /  \
   15   7

2.1. 要点

仔细分析一下后序遍历的数组postorder,翻转过来很像先序遍历,只不过现在变成先遍历右结点其次遍历左结点。

2.2. 递归

因为与105.从前序与中序遍历序列构造二叉树 解法基本一致,这里就不过多介绍了

2.2.1. 代码片段
func buildPos(inorder []int, val int) int {
	var pos int
	for i, v := range inorder {
		if v == val {
			pos = i
			break
		}
	}
	return pos
}

func buildTree(inorder []int, postorder []int) *TreeNode {
	var num = 0
	return buildTreeHelper(inorder, postorder, &num)
}

func buildTreeHelper(inorder []int, postorder []int, num *int) *TreeNode {
	if len(inorder) == 0 {
		return nil
	}
	val := postorder[len(postorder)-1-*num] //从尾往前取到根结点
	tree := &TreeNode{
		Val: val,
	}
	pos := buildPos(inorder, val)
	if pos+1 < len(inorder) {
		*num++
		tree.Right = buildTreeHelper(inorder[pos+1:], postorder, num)//这里不同点是先构建右子树,因为下一次先取到的根结点在右边而不是左边。
	}
	if pos-1 >= 0 {
		*num++
		tree.Left = buildTreeHelper(inorder[:pos], postorder, num)
	}
	return tree
}

😁😁😁制作动画过程不易,请大家顺手点赞收藏咯 谢谢~😁😁😁
如有错误欢迎指出~
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值