1.5 二叉樹(4)


二叉樹相關(guān)問題解題套路

  • 廣度優(yōu)先遍歷(BFS:Breath First Search)优训、深度優(yōu)先遍歷(DFS:Depth First Search)早敬,廣度優(yōu)先(按層)遍歷用隊(duì)列荷愕,深度優(yōu)先遍歷優(yōu)先用遞歸荐类,棧的實(shí)現(xiàn)要比遞歸復(fù)雜一些。

注意點(diǎn)

  • 換行打印需要兩個(gè)指針:一個(gè)保存當(dāng)前行的最右節(jié)點(diǎn)琅束,一個(gè)跟蹤下一行最新加入的節(jié)點(diǎn)葵腹,當(dāng)當(dāng)前行最右節(jié)點(diǎn)彈出時(shí),更新為下一行最新加入的節(jié)點(diǎn),這一行便可以跟下一行的節(jié)點(diǎn)區(qū)分開來。
  • 之字形打印鏈表需要三個(gè)指針不脯,一個(gè)保存當(dāng)前行在隊(duì)列中最后彈出的節(jié)點(diǎn)冲簿,一個(gè)保存向右遍歷時(shí)上一行的最右節(jié)點(diǎn)彤断,一個(gè)保存向左遍歷時(shí)上一行的
    最左節(jié)點(diǎn)。奇數(shù)行隊(duì)列彈出隊(duì)頭闸衫,往隊(duì)尾添加新節(jié)點(diǎn),先添加左子節(jié)點(diǎn)睛琳,后添加右子節(jié)點(diǎn)募闲;偶數(shù)行隊(duì)列彈出隊(duì)尾农渊,往隊(duì)頭添加新節(jié)點(diǎn)沼溜,先添加右子節(jié)點(diǎn),后添加左子節(jié)點(diǎn)鞍帝。

目錄

  • 從上往下打印二叉樹
  • 把二叉樹打印成多行
  • 按之字形順序打印二叉樹(較難床绪,還需要練習(xí))
  • 序列化二叉樹(不能做到bug free绩社,還需練習(xí))

從上往下打印二叉樹

從上往下打印出二叉樹的每個(gè)節(jié)點(diǎn),同層節(jié)點(diǎn)從左至右打印。

public ArrayList<Integer> PrintFromTopToBottom(TreeNode root) {
    ArrayList<Integer> res = new ArrayList<>();
    if (root == null) {
        return res;
    }
    LinkedList<TreeNode> queue = new LinkedList<>();
    queue.add(root);
    while (!queue.isEmpty()) {
        TreeNode p = queue.poll();
        res.add(p.val);
        if (p.left != null) {
            queue.add(p.left);
        }
        if (p.right != null) {
            queue.add(p.right);
        }
    }
    return res;
}

把二叉樹打印成多行

從上到下按層打印二叉樹疾渴,同一層結(jié)點(diǎn)從左至右輸出。每一層輸出一行店量。

  • 二叉樹按層打印,必然是用隊(duì)列實(shí)現(xiàn)
ArrayList<ArrayList<Integer>> Print(TreeNode pRoot) {
    ArrayList<ArrayList<Integer>> res = new ArrayList<>();
    ArrayList<Integer> list = new ArrayList<>();
    if (pRoot == null) {
        res.add(list);
        return res;
    }
    LinkedList<TreeNode> queue = new LinkedList<>();
    queue.add(pRoot);
    // last 存放當(dāng)前行最右節(jié)點(diǎn),nlast保存最新加入隊(duì)列的節(jié)點(diǎn)
    TreeNode last = pRoot, nlast = pRoot;
    while (!queue.isEmpty()) {
        TreeNode p = queue.poll();
        list.add(p);
        if (p.left != null) {
            queue.add(p.left);
            nlast = p.left;
        }
        if (p.right != null) {
            queue.add(p.right);
            nlast = p.right;
        }
        // 當(dāng)隊(duì)列彈出的節(jié)點(diǎn)跟last節(jié)點(diǎn)相同署惯,說明這一行打印完了
        // last更新為nlast,也就是下一行的最右節(jié)點(diǎn)
        if (p == last) {
            last = nlast;
            res.add(list);
            list = new ArrayList<>();
        }
    }
    return res;
}

按之字形順序打印二叉樹

請(qǐng)實(shí)現(xiàn)一個(gè)函數(shù)按照之字形打印二叉樹,即第一行按照從左到右的順序打印黄选,第二層按照從右至左的順序打印貌夕,第三行按照從左到右的順序打印啡专,其他行以此類推们童。

  • 雙向鏈表鲸鹦,奇數(shù)層往隊(duì)尾添加元素,彈出隊(duì)頭齐板;偶數(shù)層往隊(duì)頭添加元素甘磨,彈出隊(duì)尾。left監(jiān)視偶數(shù)層是否到達(dá)最左邊庵朝,right監(jiān)視奇數(shù)層是否到達(dá)最右邊
public ArrayList<ArrayList<Integer>> Print(TreeNode pRoot) {
    ArrayList<ArrayList<Integer>> res = new ArrayList<>();
    ArrayList<Integer> list = new ArrayList<>();
    if (pRoot == null) {
        return res;
    }
    LinkedList<TreeNode> queue = new LinkedList();
    queue.add(pRoot);
    boolean leftToRight = true;
    TreeNode left = pRoot, right = pRoot;
    while (!queue.isEmpty()) {
        if (leftToRight) {
            TreeNode p = queue.poll();
            list.add(p.val);
            if (p.left != null) {
                queue.add(p.left);
            }
            if (p.right != null) {
                queue.add(p.right);
            }
            if (p == right) {
                left = queue.peek();
                res.add(list);
                list = new ArrayList<>();
            }
        } else {
            TreeNode p = queue.pollLast();
            list.add(p.val);
            if (p.right != null) {
                queue.addFirst(p.right);
            }
            if (p.left != null) {
                queue.addFirst(p.left);
            }
            if (p == left) {
                right = queue.peekLast();
                res.add(list);
                list = new ArrayList<>();
            }
        }
        leftToRight = !leftToRight;
    }
    return res;
}

序列化二叉樹

請(qǐng)實(shí)現(xiàn)兩個(gè)函數(shù),分別用來序列化和反序列化二叉樹

  • 序列化和反序列化過程如果用遞歸實(shí)現(xiàn)肺蔚,對(duì)于每一個(gè)節(jié)點(diǎn)都需要不斷地將StringBuilder做toString過程宣羊,最終其實(shí)是每個(gè)字符串單獨(dú)相連接的過程,這個(gè)效率是很低的族操。所以我們選用隊(duì)列實(shí)現(xiàn)
String Serialize(TreeNode root) {
    if (root == null) {
        return "[]";
    }
    StringBuilder sb = new StringBuilder();
    LinkedList<TreeNode> q = new LinkedList<>();
    q.add(root);
    sb.append("[").append(root.val).append(",");
    while (!q.isEmpty()) {
        TreeNode p = q.poll();
        if (p.left != null) {
            sb.append(p.left.val).append(",");
            q.add(p.left);
        } else {
            sb.append("#,");
        }
        if (p.right != null) {
            sb.append(p.right.val).append(",");
            q.add(p.right);
        } else {
            sb.append("#,");
        }
    }
    return sb.deleteCharAt(sb.length() - 1).append("]").toString();
}

TreeNode Deserialize(String str) {
    if (str == null || str.equals("[]")) {
        return null;
    }
    String[] arr = str.substring(1, str.length() - 1).split(",");
    int k = 0, len = arr.length;
    LinkedList<TreeNode> q = new LinkedList<>();
    TreeNode root = new TreeNode(Integer.valueOf(arr[k++]));
    q.add(root);
    while (k < len && !q.isEmpty()) {
        TreeNode p = q.poll();
        if (k < len && !"#".equals(arr[k])) {
            p.left = new TreeNode(Integer.valueOf(arr[k]));
            q.add(p.left);
        }
        k++;
        if (k < len && !"#".equals(arr[k])) {
            p.right = new TreeNode(Integer.valueOf(arr[k]));
            q.add(p.right);
        }
        k++;
    }
    return root;
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末枷莉,一起剝皮案震驚了整個(gè)濱河市笤妙,隨后出現(xiàn)的幾起案子危喉,更是在濱河造成了極大的恐慌辜限,老刑警劉巖薄嫡,帶你破解...
    沈念sama閱讀 218,607評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件吩坝,死亡現(xiàn)場(chǎng)離奇詭異钉寝,居然都是意外死亡嵌纲,警方通過查閱死者的電腦和手機(jī)逮走,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,239評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門茅信,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蘸鲸,“玉大人棚贾,你說我怎么就攤上這事妙痹∏右粒” “怎么了耿芹?”我有些...
    開封第一講書人閱讀 164,960評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)迹炼。 經(jīng)常有香客問我斯入,道長(zhǎng)刻两,這世上最難降的妖魔是什么磅摹? 我笑而不...
    開封第一講書人閱讀 58,750評(píng)論 1 294
  • 正文 為了忘掉前任饼灿,我火速辦了婚禮赔退,結(jié)果婚禮上硕旗,老公的妹妹穿的比我還像新娘漆枚。我一直安慰自己墙基,他們只是感情好残制,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,764評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著恼布,像睡著了一般折汞。 火紅的嫁衣襯著肌膚如雪爽待。 梳的紋絲不亂的頭發(fā)上堕伪,一...
    開封第一講書人閱讀 51,604評(píng)論 1 305
  • 那天欠雌,我揣著相機(jī)與錄音富俄,去河邊找鬼霍比。 笑死悠瞬,一個(gè)胖子當(dāng)著我的面吹牛浅妆,可吹牛的內(nèi)容都是我干的凌外。 我是一名探鬼主播康辑,決...
    沈念sama閱讀 40,347評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼胸墙,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼劳秋!你這毒婦竟也來了玻淑?” 一聲冷哼從身側(cè)響起补履,我...
    開封第一講書人閱讀 39,253評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤箫锤,失蹤者是張志新(化名)和其女友劉穎谚攒,沒想到半個(gè)月后馏臭,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體括儒,經(jīng)...
    沈念sama閱讀 45,702評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡乍狐,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,893評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了烫罩。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片嗡髓。...
    茶點(diǎn)故事閱讀 40,015評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖撞秋,靈堂內(nèi)的尸體忽然破棺而出吻贿,到底是詐尸還是另有隱情,我是刑警寧澤肌割,帶...
    沈念sama閱讀 35,734評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站榨惠,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏耽装。R本人自食惡果不足惜掉奄,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,352評(píng)論 3 330
  • 文/蒙蒙 一挥萌、第九天 我趴在偏房一處隱蔽的房頂上張望引瀑。 院中可真熱鬧憨栽,春花似錦、人聲如沸屡萤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,934評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽领虹。三九已至塌衰,卻和暖如春最疆,著一層夾襖步出監(jiān)牢的瞬間蚤告,已是汗流浹背罩缴。 一陣腳步聲響...
    開封第一講書人閱讀 33,052評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工烙荷, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留檬寂,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,216評(píng)論 3 371
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像圃郊,于是被迫代替她去往敵國(guó)和親持舆。 傳聞我的和親對(duì)象是個(gè)殘疾皇子逸寓,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,969評(píng)論 2 355