劍指offer 07.重建二叉樹 | 刷題打卡

題目描述

輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建該二叉樹。假設輸入的前序遍歷和中序遍歷的結果中都不含重複的數字。node

例如,給出數組

前序遍歷 preorder = [3,9,20,15,7] 中序遍歷 inorder = [9,3,15,20,7] 返回以下的二叉樹:markdown

3
   / \
  9  20
    /  \
   15   7
複製代碼

限制:函數

0 <= 節點個數 <= 5000post

解題思路

對於一個二叉樹來講,前序遍歷的第一個元素就是二叉樹的父節點,咱們能夠根據父節點找到父節點在中序遍歷中的位置index,根據index咱們就能夠將 中序遍歷分爲左右兩個子樹,這兩個子樹也是中序遍歷。根據index咱們也能夠找到左子樹和右子樹的前序遍歷。這是咱們就能夠獲得四個數組,分別是中序遍歷的左子樹和右子樹,前序遍歷的左子樹和右子樹,因此咱們就能夠遞歸地調用函數,分別去找左子樹和右子樹的父節點,找到後賦值給node.left和node.right。結束遞歸的條件就是前序遍歷的數組只有一個元素,說明只有根元素,左右子樹爲空,就返回這個節點。ui

AC代碼

/* 前序遍歷:跟節點 + 左子樹前序遍歷 + 右子樹前序遍歷 中序遍歷:左子樹中序遍歷 + 跟節點 + 右字數中序遍歷 後序遍歷:左子樹後序遍歷 + 右子樹後序遍歷 + 跟節點 根據上面的規律: 前序遍歷找到根結點root 找到root在中序遍歷的位置 -> 左子樹的長度和右子樹的長度 截取左子樹的中序遍歷、右子樹的中序遍歷 截取左子樹的前序遍歷、右子樹的前序遍歷 遞歸重建二叉樹 */
class Node {
    constructor(data, left, right) {
        this.data = data;
        this.left = left;
        this.right = right
    }
    show() {
        console.log(this.data);
    }
};

 function rebuildTree(pre,mid) {
    if (pre.length === 0) {
        return null;
    }
    if (pre.length === 1) {
        return new Node(pre[0])
    }
    const data = pre[0];
    const index = mid.indexOf(data);
    const midLeft = mid.slice(0,index);
    const midRight = mid.slice(index+1);
    const preLeft = pre.slice(1,index+1);
    const preRight = pre.slice(index+1);
    const node = new Node(data);
    node.left = rebuildTree(preLeft,midLeft);
    node.right = rebuildTree(preRight,midRight);
    return node;
 }
 let preorder = [3,9,20,15,7];
 let inorder = [9,3,15,20,7];
console.log( rebuildTree(preorder,inorder));
複製代碼

總結

對於任意一顆樹而言,前序遍歷的形式老是this

[ 根節點, [左子樹的前序遍歷結果], [右子樹的前序遍歷結果] ]
複製代碼

即根節點老是前序遍歷中的第一個節點。而中序遍歷的形式老是spa

[ [左子樹的中序遍歷結果], 根節點, [右子樹的中序遍歷結果] ]
複製代碼

只要咱們在中序遍歷中定位到根節點,那麼咱們就能夠分別知道左子樹和右子樹中的節點數目。因爲同一顆子樹的前序遍歷和中序遍歷的長度顯然是相同的,所以咱們就能夠對應到前序遍歷的結果中,對上述形式中的全部左右括號進行定位。code

這樣以來,咱們就知道了左子樹的前序遍歷和中序遍歷結果,以及右子樹的前序遍歷和中序遍歷結果,咱們就能夠遞歸地對構造出左子樹和右子樹,再將這兩顆子樹接到根節點的左右位置。orm

本文正在參與「掘金 2021 春招闖關活動」, 點擊查看 活動詳情

相關文章
相關標籤/搜索