劍指Offer題目6:輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建出該二叉樹(Java)

面試題6:輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建出該二叉樹。假設輸入的前序遍歷和中序遍歷的結果中都不含重複的數字。例如輸入前序遍歷序列{1,2,4,7,3,5,6,8}和中序遍歷序列{4,7,2,1,5,3,8,6},則重建二叉樹並返回。node

牛客網 OJ 傳送門面試

Basic

前序遍歷、中序遍歷和後序遍歷數組

  1. 前序遍歷

根-左-右:先訪問根節點,再訪問左子節點,最後訪問右子節點。bash

  1. 中序遍歷

左-根-右:先訪問左子節點,再訪問根節點,最後訪問右子節點。ui

  1. 後序遍歷

左-右-根:先訪問左子節點,再訪問右子節點,最後訪問根節點。spa

總結:前中後序遍歷的核心:根節點最早,中間和最後訪問。3d

思路分析

題幹:重建一個二叉樹,對應返回一個根節點,這個根節點後面的子樹就是須要咱們去構建的。

Step 1: 首先,須要獲得數組中的根節點,因爲前序遍歷第一個節點就是該二叉樹的根節點,因此能夠從前序數組中
直接獲取 root node。

Step 2: 獲取到根節點以後,就能夠順藤摸瓜,去遍歷對應的左右子樹。因爲中序遍歷的根節點位於數組中間的某個
位置,根節點的左邊數組是左子樹,右邊數組是右子樹。此時就須要根據第一步獲取的根節點,從中序數組中,分割出
左右子樹所屬的兩個數組。

因爲對子樹的遍歷,本質上也都是獲取下一層的根節點,即第一層的子樹的第一個節點,相對於這個子樹就是一個根節點,
直到遞歸到葉子節點這個 base case,葉子結點也至關於一個子樹的根節點,只不過它的左右節點都是 null 而已。

所以採用遞歸解決。根據遞歸的本質--後進先出的棧--從Base case 葉子節點,挨個返回去構建一個完整的二叉樹。
複製代碼

分割數組的示意圖以下:code

代碼實現

/**
 * Definition for binary tree
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
        TreeNode root = reConstruct(pre, 0, pre.length - 1, in, 0, in.length - 1);
        return root;
    }
    
    private TreeNode reConstruct(int[] pre, int preStart, int preEnd, int[] in, int inStart, int inEnd) {
        if(preStart > preEnd || inStart > inEnd) {
            return null;
        }
        int rootValue = pre[preStart];
        TreeNode root = new TreeNode(rootValue);
        for(int i = inStart; i <= inEnd; i ++) {
            if(in[i] == rootValue) {
                root.left = reConstruct(pre, preStart + 1, preStart + i - inStart, in, inStart, i - 1);
                root.right = reConstruct(pre, preStart + i - inStart + 1, preEnd, in, i + 1, inEnd);
            }
        }
        return root;
    }
}
複製代碼

總結:重構二叉樹的場景

能夠肯定一棵二叉樹的兩個場景:cdn

  1. 已知前序和中序遍歷blog

  2. 已知中序和後序遍歷

可是,已知前序和後序遍歷,不能肯定一棵二叉樹。

拓展:根據中序和後序遍歷重構二叉樹

思路分析

Step 1:同上,根據後序遍歷的特色,根節點是最後一個才遍歷到的節點,所以咱們能夠從後序遍歷的數組中最後
一個元素獲得根節點。

Step 2: 同上,分割左右子樹對應的數組。

採用遞歸解決。

根據遞歸的本質--後進先出的棧--從Base case 葉子節點,挨個返回去構建一個完整的二叉樹。

複製代碼

代碼實現

public TreeNode reConstructBinaryTree(int[] in, int[] pos) {
        TreeNode root = reConstruct(in, 0, in.length - 1, pos, 0, pos.length - 1);
        return root;
    }
    
    private TreeNode reConstruct(int[] in, int inStart, int inEnd, int[] pos, int posStart, int posEnd){
        if(inStart > inEnd || posStart > posEnd) {
            return null;
        }
        int rootValue = pos[posEnd];
        TreeNode root = new TreeNode(rootValue);
        for(int i = inStart; i <= inEnd; i++) {
            if(in[i] == rootValue){
                root.left = reConstruct(in, inStart, i - 1, pos, posStart, posStart + i - inStart);
                root.right = reConstruct(in, i + 1, inEnd, pos, posStart + i - inStart + 1, posEnd);
            }
        }
        return toot;
    }
複製代碼
相關文章
相關標籤/搜索