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

图片.png

解题的核心是查找前序遍历和中序遍历中的根节点,左节点,右节点 三者之前的边界点, 不要看给的数据例子 把当前问题缩小例如就三个数 前序【3,9,20】 中序【9,3,20】,递归本身就是把大问题化解成相同的小问题,然后用小问题的解来处理大问题的解。
1 前序遍历是 1根节点 2 左节点 3 右节点
2 中序遍历是 1左节点 2根节点 3右节点
3 前序遍历可以确定根节点是前序数组的第一个数preorder[0]
4 查找中序遍历左右节点的边界,中序遍历根节点的位置inorder[1] ,可以发现 inorder[1]左边都是树左节点的,左节点个数是1个,即[9],inorder[1]右边都是树右节点的,右节点的个数也是1,即[20],
5 查找前序遍历左右节点的边界,前序遍历第一个节点是根节点,然后依次是左节点和右节点,而我们中序遍历不仅知道左节点的和右节点,实际上根据根节点的索引值也表示出了左节点和右节点个数,根节点索引值i是1,所以preorder[i:i+1]即[9] ,而preorder[i+1:]就是右节点,即[20]。
6 总结 边界索引里的中序遍历的根节点位置,即是表示出了根节点索引也是左节点的个数。

  1. package main
  2. import "fmt"
  3. type TreeNode struct {
  4. Val int
  5. Left *TreeNode
  6. Right *TreeNode
  7. }
  8. func buildTree(preorder []int, inorder []int) *TreeNode {
  9. if len(preorder) == 0 {
  10. return nil
  11. }
  12. rootVal := preorder[0]
  13. i := 0
  14. // 查找根节点位置
  15. for ; i < len(inorder); i++ {
  16. if rootVal == inorder[i] {
  17. break
  18. }
  19. }
  20. root := &TreeNode{Val: rootVal}
  21. root.Left = buildTree(preorder[1:i+1], inorder[:i])
  22. root.Right = buildTree(preorder[i+1:], inorder[i+1:])
  23. return root
  24. }
  25. func main() {
  26. r := buildTree([]int{3, 9, 20, 15, 7}, []int{9, 3, 15, 20, 7})
  27. printPreorder(r)
  28. fmt.Println()
  29. printInorder(r)
  30. }
  31. func printPreorder(r *TreeNode) {
  32. if r == nil {
  33. return
  34. }
  35. fmt.Print(r.Val)
  36. printPreorder(r.Left)
  37. printPreorder(r.Right)
  38. }
  39. func printInorder(r *TreeNode) {
  40. if r == nil {
  41. return
  42. }
  43. printInorder(r.Left)
  44. fmt.Print(r.Val)
  45. printInorder(r.Right)
  46. }