1. 程式人生 > >【劍指Offer學習】【面試題62:序列化二叉樹】

【劍指Offer學習】【面試題62:序列化二叉樹】

題目:請實現兩個函式,分別用來序列化和反序列化二叉樹。

解題思路

  通過分析解決前面的面試題6.我們知道可以從前序遍歷和中序遍歷構造出一棵二叉樹。受此啟發,我們可以先把一棵二叉樹序列化成一個前序遍歷序列和一箇中序序列,然後再反序列化時通過這兩個序列重構出原二叉樹。
  這個思路有兩個缺點。一個缺點是該方法要求二叉樹中不能用有數值重複的結點。另外只有當兩個序列中所有資料都讀出後才能開始反序列化。如果兩個遍歷序列的資料是從一個流裡讀出來的,那就可能需要等較長的時間。
  實際上如果二叉樹的序列化是從根結點開始的話,那麼相應的反序列化在根結點的數值讀出來的時候就可以開始了。因此我們可以根據前序遍歷的順序來序列化二叉樹,因為前序遍歷是從根結點開始的。當在遍歷二叉樹碰到NULL指標時,這些NULL指標序列化成一個特殊的字元(比如‘$’)。另外,結點的數值之間要用一個特殊字元(比如’,’)隔開。

結點定義

private static class BinaryTreeNode {
    private int val;
    private BinaryTreeNode left;
    private BinaryTreeNode right;

    public BinaryTreeNode() {
    }

    public BinaryTreeNode(int val) {
        this.val = val;
    }

    @Override
    public String toString() {
        return
val + ""; } }

程式碼實現

import java.util.LinkedList;
import java.util.List;

public class Test62 {
    private static class BinaryTreeNode {
        private int val;
        private BinaryTreeNode left;
        private BinaryTreeNode right;

        public BinaryTreeNode() {
        }

        public
BinaryTreeNode(int val) { this.val = val; } @Override public String toString() { return val + ""; } } public static void serialize(BinaryTreeNode root, List<Integer> result) { List<BinaryTreeNode> list = new LinkedList<>(); list.add(root); BinaryTreeNode node; while (list.size() > 0) { node = list.remove(0); if (node == null) { result.add(null); }else { result.add(node.val); list.add(node.left); list.add(node.right); } } } public static BinaryTreeNode deserialize(List<Integer> result, int idx) { if (result.size() < 1 || idx < 0 || result.size() <= idx || result.get(idx) == null) { return null; } BinaryTreeNode root = new BinaryTreeNode(result.get(idx)); root.left = deserialize(result, idx * 2 + 1); root.right = deserialize(result, idx * 2 + 2); return root; } public static void main(String[] args) { test01(); } private static void test01() { BinaryTreeNode n1 = new BinaryTreeNode(1); BinaryTreeNode n2 = new BinaryTreeNode(2); BinaryTreeNode n3 = new BinaryTreeNode(3); BinaryTreeNode n4 = new BinaryTreeNode(4); BinaryTreeNode n5 = new BinaryTreeNode(5); BinaryTreeNode n6 = new BinaryTreeNode(6); BinaryTreeNode n7 = new BinaryTreeNode(7); BinaryTreeNode n8 = new BinaryTreeNode(8); BinaryTreeNode n9 = new BinaryTreeNode(9); n1.left = n2; n1.right = n3; n2.left = n4; n2.right = n5; n3.left = n6; n3.right = n7; n4.left = n8; n4.right = n9; List<Integer> result = new LinkedList<>(); serialize(n1, result); System.out.println(result); System.out.println(); BinaryTreeNode root = deserialize(result, 0) ; print(root); } private static void print(BinaryTreeNode root) { if (root != null) { print(root.left); System.out.printf("%-3d", root.val); print(root.right); } } }

執行結果

這裡寫圖片描述

特別說明

相關推薦

Offer學習試題62序列化二

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

offer》第三十七題(序列化二

nbsp pre 三十七 === eof istream node nod style // 面試題37:序列化二叉樹 // 題目:請實現兩個函數,分別用來序列化和反序列化二叉樹。 #include "BinaryTree.h" #include <io

Offer學習試題6 重建二

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

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步,然後兩個指標以相同的速度向前移動。當第二個指標

Offer學習試題60把二打印出多行

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

Offer學習試題50中兩個結點的最低公共祖先

題目:求樹中兩個結點的最低公共祖先,此樹不是二叉樹,並且沒有指向父節點的指標。 樹的結點定義 private static class TreeNode { int val; List<TreeNode> childre

Offer學習試題67機器人的運動範圍

題目:地上有個m行n列的方格。一個機器人從座標(0,0)的格子開始移動,它每一次可以向左、右、上、下移動一格,但不能進入行座標和列座標的數位之和大於k的格子。 舉例分析   例如,當k為18時,機器人能夠進入方格(35,37),因為3+5+3+7=1

Offer學習試題31連續子陣列的最大和

題目:輸入一個整型陣列,數組裡有正數也有負數。陣列中一個或連續的多個整陣列成一個子陣列。求所有子陣列的和的最大值。要求時間複雜度為O(n)。 例子說明: 例如輸入的陣列為{1, -2, 3, 10, -4, 7, 2, -5},和最大的子陣列為{3,

Offer學習試題54表示數值的字串

題目:請實現一個函式用來判斷字串是否表示數值(包括整數和小數)。 例子說明   例如,字串“+100”,“5e2”,“-123”,“3.1416”及”-1E-16”都表示數值,但“12e”,”1a3.14”,”1.2.3”,”+-5”及“12e+5.

Offer學習試題18 的子結構

題目:輸入兩棵二叉樹A 和B,判斷B 是不是A 的子結構。 二叉樹結點的定義: /** * 二叉樹的樹結點 */ public static class BinaryTreeNode { int value; BinaryT

Offer學習試題13 在O(1)時間刪除連結串列結點

程式碼實現: public class Test13 { /** * 連結串列結點 */ public static class ListNode { int value; // 儲存連結串列的值 L

Offer學習試題11 數值的整數次方

程式碼實現: public class Test11 { /** * 實現函式double Power(double base, int exponent),求base的exponent次方。 * 不得使用庫函式,同時不需要考慮大數問題。

Offer學習試題36陣列中的逆序對

題目:在陣列中的兩個數字如果前面一個數字大於後面的數字,則這兩個數字組成一個逆序對。輸入一個數組,求出這個陣列中的逆序對的總數。 舉例分析   例如在陣列{7, 5, 6, 4 中, 一共存在5 個逆序對,分別是(7, 6)、(7,5),(7, 4)

Offer學習試題28 字串的排列

題目:輸入一個字串,打印出該字串中字元的所有排列。例如輸入字串abc。則打印出由字元a、b、c 所能排列出來的所有字串abc、acb、bac 、bca、cab 和cba 。 解題思路: 把一個字串看成由兩部分組成:第一部分為它的第一個字元,第二部分是後面