105. 从前序与中序遍历序列构造二叉树 Link to heading
描述 Link to heading
根据一棵树的前序遍历与中序遍历构造二叉树。
注意: 你可以假设树中没有重复的元素。
例如,给出
前序遍历 preorder = [3,9,20,15,7] 中序遍历 inorder = [9,3,15,20,7] 返回如下的二叉树:
3 / \ 9 20 / \ 15 7https://leetcode-cn.com/problems/construct-binary-tree-from-preorder-and-inorder-traversal
思路 Link to heading
- 由先序序列第一个
pre[0]在中序序列中找到根节点位置gen - 以
gen为中心遍历0~gen左子树- 子中序序列:
0~gen-1,放入vin_left[] - 子先序序列:
1~gen放入pre_left[],+1可以看图,因为头部有根节点
- 子中序序列:
gen+1~vinlen为右子树- 子中序序列:
gen+1 ~ vinlen-1**放入vin_right[] - 子先序序列:
gen+1 ~ vinlen-1**放入pre_right[]
- 子中序序列:
- 由先序序列
pre[0]创建根节点 - 连接左子树,按照左子树子序列递归(
pre_left[]和vin_left[]) - 连接右子树,按照右子树子序列递归(
pre_right[]和vin_right[]) - 返回根节点


解答 Link to heading
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func buildTree(preorder []int, inorder []int) *TreeNode {
if preorder == nil || inorder == nil ||
len(preorder) == 0 || len(inorder) == 0 {
return nil
}
// 中顺序列找根结点
var root int
for k, v := range inorder {
if v == preorder[0] {
root = k
break
}
}
// 左右子树归类
// pre_left, pre_right := preorder[1: root+1], preorder[root+1:]
// in_left, in_right := inorder[0: root], inorder[root+1:]
// 左右子树递归
return &TreeNode{
Val: preorder[0],
Left: buildTree(preorder[1: root+1], inorder[: root]),
Right: buildTree(preorder[root+1:], inorder[root+1:]),
}
}
结果和优化 Link to heading
执行用时 :4 ms, 在所有 Go 提交中击败了95.95%的用户 内存消耗 :3.9 MB, 在所有 Go 提交中击败了68.15%的用户
原则:
- 能不创建变量就不创建
- 要用的时候再创建(因为可能提前退出)
- 语言本身能实现的优先交给语言来:line30,31 直接用切片不香吗,就没必要自己创建变量写循环了
106. 从中序与后序遍历序列构造二叉树 Link to heading
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func buildTree(inorder []int, postorder []int) *TreeNode {
l := len(postorder)
if l == 0 {
return nil
}
// post:9, 15, 7, 20, 3
// in: 9, 3, 15, 20, 7
var k, v int
for k, v = range inorder {
if v == postorder[l-1] {
break
}
}
return &TreeNode{
Val: v,
Left: buildTree(inorder[:k], postorder[:k]),
Right: buildTree(inorder[k+1:], postorder[k: l-1]),
}
}