[算法]剑指offer p6 重建二叉树 golang
题目
题目:输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建出图2.6所示的二叉树并输出它的头结点。二叉树结点的定义如下:
type BTree struct {
Data int
Left *BTree
Right *BTree
}
思路
举例发现规律解决问题
- 前序遍历: 当前节点 -> 左子树 -> 右子树
- 中序遍历: 左子树 -> 当前节点 -> 右子树
我们可以发现就是左子树和当前节点的打印顺序不一样
前序遍历的第一个节点是根节点1
在中序遍历中1的左边是左子树,右边是右子树
前序遍历 2
中序遍历的 2 的左边是 2 的左子树, 右边没有就是没有右子树
前序遍历 4
中序遍历的 4 的右边是 7 为 4 的右子树
前序遍历 7
7 没有左子树也没有右子树旧返回
右子树也是同理的
代码(golang)
//二叉树
type BTree struct {
Data int
Left *BTree
Right *BTree
}
//通过前序遍历顺序和中序遍历循序构建二叉树返回根节点
func BuildBTree(preOrder []int, midOrder []int) (root *BTree) {
// 参数处理
if len(preOrder) == 0 || len(midOrder) == 0 || len(preOrder) != len(midOrder) {
fmt.Printf("%s\n", "参数错误")
return
}
//todo 参数处理,2个数组元素需要一致
preIndex := 0
return buildBTree(preOrder, midOrder, &preIndex)
}
//递归
//preIndex 是前序遍历的当前遍历节点
func buildBTree(preOrder []int, midOrder []int, preIndex *int) (root *BTree) {
//如果midOrder只有一个节点就返回该节点,没有节点就返回nil
if len(midOrder) == 0 {
return nil
}
midVal := preOrder[*preIndex]
*preIndex++
//赋值该节点
root = &BTree{Data: midVal}
if len(midOrder) == 1 {
return
}
//找到中序遍历的节点的值和 midIndex
midIndex := 0
for i := 0; i < len(midOrder); i++ {
if midVal == midOrder[i] {
midIndex = i
break
}
}
//切割midOrder左边并递归
root.Left = buildBTree(preOrder, midOrder[:midIndex], preIndex)
if midIndex != len(midOrder) {
//todo 切割arr溢出
//切割midOrder右边边并递归
root.Right = buildBTree(preOrder, midOrder[midIndex+1:], preIndex)
}
return
}
测试
//返回 exampel1 二叉树实例
func E1Except() (root *BTree) {
//构造数据
E1 := &BTree{Data: 1}
E2 := &BTree{Data: 2}
E3 := &BTree{Data: 3}
E4 := &BTree{Data: 4}
E5 := &BTree{Data: 5}
E6 := &BTree{Data: 6}
E7 := &BTree{Data: 7}
E8 := &BTree{Data: 8}
E1.Left = E2
E2.Left = E4
E4.Right = E7
E1.Right = E3
E3.Left = E5
E3.Right = E6
E6.Left = E8
return E1
}
func TestP6(t *testing.T) {
examples := []struct {
preOrder []int
midOrder []int
except *BTree
}{
{
preOrder: []int{1, 2, 4, 7, 3, 5, 6, 8},
midOrder: []int{4, 7, 2, 1, 5, 3, 8, 6},
except: E1Except(),
},
{
preOrder: []int{},
midOrder: []int{},
except: nil,
},
}
for _, e := range examples {
assert.Equal(t, e.except, BuildBTree(e.preOrder, e.midOrder))
}
}
TODO:
- 检查前序遍历和中序遍历的数据问题