题目概述
- 算法说明
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。 - 测试用例
输入:
[1,2,3,4,5,6,7],[3,2,4,1,6,5,7]
返回值:
{1,2,5,3,4,6,7}
解析&参考答案
- 解析
先通过中序遍历找到根节点,然后通过先序遍历找到左子树和右子树的分隔点,从而分别得到左子树和右子树的先序、中序遍历;然后递归得到整颗树。 - 参考答案
vim jz04.go
package main
import "fmt"
type TreeNode struct {
Val int
Left *TreeNode
Right *TreeNode
}
func PrintPreOrder(node *TreeNode) {
if node == nil {
return
}
fmt.Print(node.Val, ",")
PrintPreOrder(node.Left)
PrintPreOrder(node.Right)
}
func PrintInfixOrder(node *TreeNode) {
if node == nil {
return
}
PrintInfixOrder(node.Left)
fmt.Print(node.Val, ",")
PrintInfixOrder(node.Right)
}
func PrintPostOrder(node *TreeNode) {
if node == nil {
return
}
PrintPostOrder(node.Left)
PrintPostOrder(node.Right)
fmt.Print(node.Val, ",")
}
func reConstructBinaryTree(pre []int, vin []int) *TreeNode {
if len(pre) == 0 || len(vin) == 0 {
return nil
}
root := &TreeNode{pre[0], nil, nil}
pos := 0
for i, v := range vin {
if v == pre[0] {
pos = i
break
}
}
if pos != 0 {
preL := pre[1 : pos+1]
preR := pre[pos+1:]
vinL := vin[:pos]
vinR := vin[pos+1:]
root.Left = reConstructBinaryTree(preL, vinL)
root.Right = reConstructBinaryTree(preR, vinR)
} else {
preR := pre[pos+1:]
vinR := vin[pos+1:]
root.Right = reConstructBinaryTree(preR, vinR)
}
return root
}
func main() {
root := &TreeNode{1,
&TreeNode{2, &TreeNode{4, nil, &TreeNode{7, nil, nil}}, nil},
&TreeNode{3, &TreeNode{5, nil, nil},
&TreeNode{6, &TreeNode{8, nil, nil}, nil}}}
PrintPreOrder(root)
fmt.Println()
PrintInfixOrder(root)
fmt.Println()
PrintPostOrder(root)
result := reConstructBinaryTree([]int{1, 2, 4, 7, 3, 5, 6, 8}, []int{4, 7, 2, 1, 5, 3, 8, 6})
fmt.Println()
PrintPreOrder(result)
}
注意事项
- to add
说明
- 当前使用 go1.15.8
- 参考 牛客网--剑指offer
标题中jzn(n为具体数字)代表牛客网剑指offer系列第n号题目,例如 jz01 代表牛客网剑指offer中01号题目。
注意!!!
- 笔者最近在学习 golang,因此趁机通过数据结构和算法来进一步熟悉下go语言
- 当前算法主要来源于剑指 offer,后续会进一步补充 LeetCode 上重要算法,以及一些经典算法
- 此处答案仅为参考,不一定是最优解,欢迎感兴趣的读者在评论区提供更优解