golang刷leetcode---105.从前序与中序遍历序列构造二叉树

一、题目描述:

根据一棵树的前序遍历与中序遍历构造二叉树。
注意:你可以假设树中没有重复元素。
示例:

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

返回如下的二叉树:

     3
   /   \
  9    20
       / \
      15  7
二、思路分析
  1. 二叉树前序遍历顺序:中左右。即先遍历根节点,随后遍历左子树,最后遍历右子树。
  2. 二叉树中序遍历顺序:左中右。即先遍历左子树,再遍历根节点,最后遍历右子树。
  3. 二叉树后序遍历顺序:左右中。即先遍历左子树,再遍历右子树,最后遍历根节点。

递归地遍历某个子树的过程中,也是将这棵子树看成一颗全新的树。其实我们根据前序和中序就能得到一棵完整的二叉树。而且题目中要求:可以假设树中没有重复元素。这样就能得到一棵唯一的二叉树。

递归方法:

对于任意一棵树而言,根节点总是前序遍历的第一个节点。
前序遍历:[根节点,[左子树所有的节点],[右子树所有的节点]]
中序遍历:[[左子树所有的节点],根节点,[右子树所有的节点]]

只要我们在中序遍历中找到根节点的位置,我们就可以分别知道左子树和右子树的节点个数。由于同一棵子树的前序和中序的长度显然是相同的,因此找到左子树和右子树的起始位置和结束位置。

三、代码实现
/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func buildTree(preorder []int, inorder []int) *TreeNode {
	//若preorder的长度为0,说明这是棵空的二叉树
	if len(preorder)==0{
		return nil
	}
	//根据二叉树前序遍历的第一个节点是根节点的特性,可以定义一个只有根节点的二叉树;然后再递归遍历左右子树来填充这棵二叉树。
	root:=&preorder{
		preorder[0],
		nil,
		nil,
	}
	//遍历中序序列中的节点,找到根节点在中序中位置
	i:=0
	for ;i<len(inorder);i++{
		if inorder[i]==preorder[0]{
			break
		}
	}
	
	//根据中序遍历的特点:[[左子树],根节点,[右子树]]来确定左右子树的起始位置和结束位置
	//遍历左子树:
	//前序参数中:第一个是根节点,所以起始位置从1开始,结束位置是中序序列i前面节点的个数,+1是因为slice截取原则:左闭右开;中序参数中:起始位置就是从头开始,到i位置结束。
	root.Left=buildTree(preorder[1:len(inorder[:i])+1],inorder[:i])
	//遍历右子树
	//前序参数是:从[中序序列i前面节点的个数+1]开始,到最后结束;中序参数是:从i位置的后一个开始到最后结束
	root.Right=buildTree(preorder[len(inorder[:i])+1:],inorder[i+1:])

	return root
}
四、复杂度分析:
  • 时间复杂度:O(n),其中n是树中的节点个数。
  • 空间复杂度:O(n),除去返回的答案需要的O(n)空间外,我们还需要使用O(n)的空间存储哈希映射,以及O(h)(h代表树高),的空间表示递归时的栈空间。这里h

你可能感兴趣的:(leetcode)