1. 程式人生 > >【劍指Offer學習】【面試題6 :重建二叉樹】

【劍指Offer學習】【面試題6 :重建二叉樹】


題目:輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建出該二叉樹。假設輸入的前序遍歷和中序遍歷的結果中都不含重複的數字。例如:前序遍歷序列{ 1, 2, 4, 7, 3, 5, 6, 8}和中序遍歷序列{4, 7, 2, 1, 5, 3, 8,6},重建出下圖所示的二叉樹並輸出它的頭結點。


程式碼如下:

public class Test06 {
    /**
     * 二叉樹節點類
     */
    public static class BinaryTreeNode {
        int value;
        BinaryTreeNode left;
        BinaryTreeNode right;
    }

    /**
     * 輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建出該二節樹。假設輸入的前序遍歷和中序遍歷的結果中都不含重複的數字。
     *
     * @param preorder 前序遍歷
     * @param inorder  中序遍歷
     * @return 樹的根結點
     */
    public static BinaryTreeNode construct(int[] preorder, int[] inorder) {
        // 輸入的合法性判斷,兩個陣列都不能為空,並且都有資料,而且資料的數目相同
        if (preorder == null || inorder == null || preorder.length != inorder.length || inorder.length < 1) {
            return null;
        }

        return construct(preorder, 0, preorder.length - 1, inorder, 0, inorder.length - 1);
    }

    /**
     * 輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建出該二節樹。假設輸入的前序遍歷和中序遍歷的結果中都不含重複的數字。
     *
     * @param preorder 前序遍歷
     * @param ps       前序遍歷的開始位置
     * @param pe       前序遍歷的結束位置
     * @param inorder  中序遍歷
     * @param is       中序遍歷的開始位置
     * @param ie       中序遍歷的結束位置
     * @return 樹的根結點
     */
    public static BinaryTreeNode construct(int[] preorder, int ps, int pe, int[] inorder, int is, int ie) {

        // 開始位置大於結束位置說明已經沒有需要處理的元素了
        if (ps > pe) {
            return null;
        }
        // 取前序遍歷的第一個數字,就是當前的根結點
        int value = preorder[ps];
        int index = is;
        // 在中序遍歷的陣列中找根結點的位置
        while (index <= ie && inorder[index] != value) {
            index++;
        }

        // 如果在整個中序遍歷的陣列中沒有找到,說明輸入的引數是不合法的,丟擲異常
        if (index > ie) {
            throw new RuntimeException("Invalid input");
        }

        // 建立當前的根結點,並且為結點賦值
        BinaryTreeNode node = new BinaryTreeNode();
        node.value = value;

        // 遞迴構建當前根結點的左子樹,左子樹的元素個數:index-is+1個
        // 左子樹對應的前序遍歷的位置在[ps+1, ps+index-is]
        // 左子樹對應的中序遍歷的位置在[is, index-1]
        node.left = construct(preorder, ps + 1, ps + index - is, inorder, is, index - 1);
        // 遞迴構建當前根結點的右子樹,右子樹的元素個數:ie-index個
        // 右子樹對應的前序遍歷的位置在[ps+index-is+1, pe]
        // 右子樹對應的中序遍歷的位置在[index+1, ie]
        node.right = construct(preorder, ps + index - is + 1, pe, inorder, index + 1, ie);

        // 返回建立的根結點
        return node;
    }

    // 中序遍歷二叉樹
    public static void printTree(BinaryTreeNode root) {
        if (root != null) {
            printTree(root.left);
            System.out.print(root.value + " ");
            printTree(root.right);
        }

    }

    // 普通二叉樹
    //              1
    //           /     \
    //          2       3
    //         /       / \
    //        4       5   6
    //         \         /
    //          7       8
    private static void test1() {
        int[] preorder = {1, 2, 4, 7, 3, 5, 6, 8};
        int[] inorder = {4, 7, 2, 1, 5, 3, 8, 6};
        BinaryTreeNode root = construct(preorder, inorder);
        printTree(root);
    }

    // 所有結點都沒有右子結點
    //            1
    //           /
    //          2
    //         /
    //        3
    //       /
    //      4
    //     /
    //    5
    private static void test2() {
        int[] preorder = {1, 2, 3, 4, 5};
        int[] inorder = {5, 4, 3, 2, 1};
        BinaryTreeNode root = construct(preorder, inorder);
        printTree(root);
    }

    // 所有結點都沒有左子結點
    //            1
    //             \
    //              2
    //               \
    //                3
    //                 \
    //                  4
    //                   \
    //                    5
    private static void test3() {
        int[] preorder = {1, 2, 3, 4, 5};
        int[] inorder = {1, 2, 3, 4, 5};
        BinaryTreeNode root = construct(preorder, inorder);
        printTree(root);
    }

    // 樹中只有一個結點
    private static void test4() {
        int[] preorder = {1};
        int[] inorder = {1};
        BinaryTreeNode root = construct(preorder, inorder);
        printTree(root);
    }

    // 完全二叉樹
    //              1
    //           /     \
    //          2       3
    //         / \     / \
    //        4   5   6   7
    private static void test5() {
        int[] preorder = {1, 2, 4, 5, 3, 6, 7};
        int[] inorder = {4, 2, 5, 1, 6, 3, 7};
        BinaryTreeNode root = construct(preorder, inorder);
        printTree(root);
    }

    // 輸入空指標
    private static void test6() {
        construct(null, null);
    }

    // 輸入的兩個序列不匹配
    private static void test7() {
        int[] preorder = {1, 2, 4, 5, 3, 6, 7};
        int[] inorder = {4, 2, 8, 1, 6, 3, 7};
        BinaryTreeNode root = construct(preorder, inorder);
        printTree(root);
    }


    public static void main(String[] args) {

        test1();
        System.out.println();
        test2();
        System.out.println();
        test3();
        System.out.println();
        test4();
        System.out.println();
        test5();
        System.out.println();
        test6();
        System.out.println();
        test7();

    }
}

執行結果:


相關推薦

Offer學習試題6 重建

題目:輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建出該二叉樹。假設輸入的前序遍歷和中序遍歷的結果中都不含重複的數字。例如:前序遍歷序列{ 1, 2, 4, 7, 3, 5, 6, 8}和中序遍歷序列{4, 7, 2, 1, 5, 3, 8,6},重建出下圖所示的二叉

offer試題7重建

題目:輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建該二叉樹。假設輸入的前序遍歷和中序遍歷的結果中都不含重複的數字。 二叉樹節點的定義如下: struct BinaryTreeNode { int m_nValue; BinaryTreeNode* m_pLeft; Binar

offer試題7重建(Java實現)

題目:輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建出該二叉樹。假設輸入的前序遍歷和中序遍歷的結果中都不含重複的數字。例如輸入前序遍歷序列{1,2,4,7,3,5,6,8}和中序遍歷序列{4,7,2,1,5,3,8,6},則重建二叉樹並返回。 思路:可以把二叉樹分為左右子樹分別構建,前序

Offer(第二版)試題7重建

劍指Offer面試題7:重建二叉樹題目:輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建該二叉樹。假設輸入的前序遍歷和中序遍歷中都不包含重複的數字。例如前序遍歷序列為{1,2,4,5,3,7,6}和中序遍歷序列{4,2,5,1,7,3,6},則可以重建一棵二叉樹。如圖所示:  

試題7重建

style ext str null value var int cti 二叉樹 <?php header("content-type:text/html;charset=utf-8"); /* *重建二叉樹 P62 */ class TreeNode {

Offer學習試題60打印出多行

題目:從上到下按層列印二叉樹,同一層的結點按從左到右的順序列印,每一層列印一行。 解題思路   用一個佇列來儲存將要列印的結點。為了把二叉樹的每一行單獨列印到一行裡,我們需要兩個變數:一個變量表示在當前的層中還沒有列印的結點數,另一個變量表示下一次結

Offer學習試題62序列化二

題目:請實現兩個函式,分別用來序列化和反序列化二叉樹。 解題思路   通過分析解決前面的面試題6.我們知道可以從前序遍歷和中序遍歷構造出一棵二叉樹。受此啟發,我們可以先把一棵二叉樹序列化成一個前序遍歷序列和一箇中序序列,然後再反序列化時通過這兩個序列

offer--試題60列印成多行

題目描述 從上到下按層列印二叉樹,同一層結點從左至右輸出。每一層輸出一行。 python實現: # -*- coding:utf-8 -*- # class TreeNode: #     de

Offer試題59對稱 Java實現

/************************************************************** * Copyright (c) 2016, * All rights reserved. * 版 本 號:v1.0

offer——(13)從上往下列印

遵從先上後下,先左後右的原則,用if——else遞迴即可。  import java.util.ArrayList; /** public class TreeNode { int val = 0; TreeNode left = null; Tree

offer 31. 不分行從上往下列印

從上往下打印出二叉樹的每個結點,同一層的結點按照從左到右的順序列印。 樣例 輸入如下圖所示二叉樹[8, 12, 2, null, null, 6, null, 4, null, null, null] 8 / \ 12 2 / 6 /

offer(23)——從上往下列印

題目 從上往下打印出二叉樹的每個結點,同一層的結點按照從左到右的順序列印 分析 從上到下列印,即就是按層遍歷這棵二叉樹,然後將其節點上的值打印出來。如果該樹只有一個根結點,那麼就直接列印該節點就好,這是一種最極端的情況,可是我們常常遇到的並不是這樣的情況,即就是列印完一個結

offer:數字在排序陣列中出現的次數&的深度&平衡

37.數字在排序陣列中出現的次數 /* 題目描述 統計一個數字在排序陣列中出現的次數。 */ class Solution { public: int GetNumberOfK(vector<int> data ,int k) {

Offer學習所有試題匯總

tails 超過一半 奇數 正則表達式 detail 刪除 祖先 滑動窗口 翻轉單詞順序 劍指Offer學習   劍指Offer這本書已經學習完了,從中也學習到了不少的東西,現在做一個總的目錄,供自已和大家一起參考,學如逆水行舟,不進則退。只有不斷地學習才能跟上時候,跟得

Offer學習試題5 從尾到頭列印連結串列思路

方案一:(後進先出)遍歷連結串列,再從棧頂開始出個輸出結點的值,此時輸出的結點的順序已經反轉過來了。 先推進棧 再依次取出棧頂元素 方案二:遞迴。 判斷連結串列頭結點是否為空 將 next 結點作為下一次的實參 輸出當前棧頂元素。 缺點:當連結串

Offer學習所有試題彙總

劍指Offer學習   劍指Offer這本書已經學習完了,從中也學習到了不少的東西,現在做一個總的目錄,供自已和大家一起參考,學如逆水行舟,不進則退。只有不斷地學習才能跟上時候,跟得上技術的潮流! 目錄 第01-10題 第11-20題 第21-30題

Offer學習試題4 替換空格思路

題目: 請實現一個函式,將一個字串中的每個空格替換成“%20”。例如,當字串為We Are Happy,則經過替換之後的字串為We%20Are%20Happy。 思路: 遍歷的方向兩邊皆可。 若從後往前遍歷,新的字串需要反轉。 用 String 類的方法判斷字串

Offer學習試題5 從尾到頭列印連結串列

題目:輸入個連結串列的頭結點,從尾到頭反過來打印出每個結點的值。 public class Test05 { /** * 結點物件 */ public s

Offer學習試題26複雜連結串列的複製

題目:請實現函式ComplexListNode clone(ComplexListNode head),複製一個複雜連結串列。在複雜連結串列中,每個結點除了有一個next 域指向下一個結點外,還有一個sibling 指向連結串列中的任意結點或者null。

Offer學習試題56連結串列中環的入口結點

題目:一個連結串列中包含環,如何找出環的入口結點? 解題思路   可以用兩個指標來解決這個問題。先定義兩個指標P1和P2指向連結串列的頭結點。如果連結串列中環有n個結點,指標P1在連結串列上向前移動n步,然後兩個指標以相同的速度向前移動。當第二個指標