經(jīng)典問題剖析-由前序、中序遍歷序列構(gòu)造二叉樹(java/kotlin)

一碌嘀、題目

根據(jù)一棵樹的前序遍歷與中序遍歷構(gòu)造二叉樹涣旨。
注意:
你可以假設(shè)樹中沒有重復(fù)的元素。
示例:給出

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

二筏餐、遞歸解法

1. 解題思路

清楚前序遍歷和中序遍歷的過程:

  • 前序遍歷:根开泽、左、右
  • 中序遍歷:左魁瞪、根穆律、右
  • 將前序、中序序列做如下圖切割导俘,可以看到是明顯的遞歸調(diào)用
前序峦耘、中序序列分割圖
  • 前序序列中,preOrder[preLeft]為根節(jié)點(diǎn)旅薄,通過值找到根節(jié)點(diǎn)在中序序列中的index辅髓,記為pIndex。由于樹中沒有重復(fù)的元素少梁,這個(gè)過程可以使用一個(gè)hash表存儲(chǔ)index洛口,節(jié)點(diǎn)值value作為hashKey,index作為hashValue
  • 通過根節(jié)點(diǎn)分割的左右子樹邊界通過preLeft凯沪、preRight第焰、inLeft、inRight妨马、pIndex表示挺举,得到左右子樹的前序、中序序列烘跺。其中中序遍歷的左右子樹的邊界很容就知道是[inLeft湘纵,pIndex - 1][pIndex + 1, inRight];前序遍歷中滤淳,左子樹的右邊界比較不好一眼看出來梧喷,我們可以稍微計(jì)算一下,左子樹右邊界 - (preLeft + 1) = pIndex -1 - inLeft,由這個(gè)公式可得出左子樹右邊界 = pIndex - inLeft + preLeft铺敌,自然而然右子樹的左邊界就是pIndex - inLeft + preLeft + 1绊困,所以前序遍歷左右子樹的邊界就是[preLeft + 1, pIndex - inLeft + preLeft][pIndex - inLeft + preLeft + 1, preRight]。不要嫌麻煩适刀,其實(shí)這道題關(guān)鍵就是邊界值的表示,沒有什么難的煤蹭。
  • 遞歸結(jié)束條件:preLeft > preRight笔喉,相等的時(shí)候就是葉子結(jié)點(diǎn)。

2. 編碼

由解題思路硝皂,很容易寫出此題的遞歸解法代碼常挚。
示例代碼:

class BTreeNode(val value: Int) {
    var left: BTreeNode? = null
    var right: BTreeNode? = null
}

fun buildBTreeByPreOrderAndInOrder(preOrder: IntArray, inOrder: IntArray): BTreeNode? {
    val inOrderIndexHashMap = mutableMapOf<Int, Int>()
    inOrder.forEachIndexed { index, data ->
        inOrderIndexHashMap[data] = index
    }
    return buildBTreeNode(preOrder, inOrderIndexHashMap, 0, preOrder.size - 1, 0, inOrder.size - 1)
}

fun buildBTreeNode(preOrder: IntArray, indexMap: MutableMap<Int, Int>, preOrderLeft: Int, preOrderRight: Int, inOrderLeft: Int, inOrderRight: Int): BTreeNode? {
    if (preOrderLeft > preOrderRight) {
        return null
    }
    //根節(jié)點(diǎn)
    val root = BTreeNode(preOrder[preOrderLeft])
    //通過跟節(jié)點(diǎn)的value值找在inOrder中的index
    val index = indexMap[preOrder[preOrderLeft]] ?: return null
    //找左子樹的在preOrder和inOrder中的左右index

    //左子樹 在preOrder中的左右index
    val leftChildTreeOnPreOrderIndexLeft = preOrderLeft + 1
    val leftChildTreeOnPreOrderIndexRight = index - inOrderLeft + preOrderLeft
    //左子樹 在inOrder中的左右index
    val leftChildTreeOnInOrderIndexLeft = inOrderLeft
    val leftChildTreeOnInOrderIndexRight = index - 1


    //右子樹 在preOrder中的左右index
    val rightChildTreeOnPreOrderIndexLeft = leftChildTreeOnPreOrderIndexRight + 1
    val rightChildTreeOnPreOrderIndexRight = preOrderRight
    //右子樹 在inOrder中的左右index
    val rightChildTreeOnInOrderIndexLeft = index + 1
    val rightChildTreeOnInOrderIndexRight = inOrderRight

    root.left = buildBTreeNode(preOrder, indexMap, leftChildTreeOnPreOrderIndexLeft, leftChildTreeOnPreOrderIndexRight, leftChildTreeOnInOrderIndexLeft, leftChildTreeOnInOrderIndexRight)
    root.right = buildBTreeNode(preOrder, indexMap, rightChildTreeOnPreOrderIndexLeft, rightChildTreeOnPreOrderIndexRight, rightChildTreeOnInOrderIndexLeft, rightChildTreeOnInOrderIndexRight)
    return root
}

3. 時(shí)空復(fù)雜度分析

時(shí)間復(fù)雜度:數(shù)組中每個(gè)值都要訪問構(gòu)建二叉樹節(jié)點(diǎn),所以時(shí)間復(fù)雜度為O(N)
空間復(fù)雜度:使用Hash表存儲(chǔ)根節(jié)點(diǎn)的index稽物,需要O(N)的空間奄毡,最多有O(logN)個(gè)函數(shù)調(diào)用,所以空間復(fù)雜度是O(N)

四贝或、總結(jié)

  • 此題難度中等
  • 經(jīng)典題目吼过,關(guān)鍵是找到根節(jié)點(diǎn)、左咪奖、右子樹邊界分別在在前序盗忱、中序序列中的index、leftIndex羊赵、rightIndex即可

leetcode傳送門:105. 從前序與中序遍歷序列構(gòu)造二叉樹

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末趟佃,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子昧捷,更是在濱河造成了極大的恐慌闲昭,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,858評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件靡挥,死亡現(xiàn)場(chǎng)離奇詭異序矩,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)芹血,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門贮泞,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人幔烛,你說我怎么就攤上這事啃擦。” “怎么了饿悬?”我有些...
    開封第一講書人閱讀 165,282評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵令蛉,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我,道長(zhǎng)珠叔,這世上最難降的妖魔是什么蝎宇? 我笑而不...
    開封第一講書人閱讀 58,842評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮祷安,結(jié)果婚禮上姥芥,老公的妹妹穿的比我還像新娘。我一直安慰自己汇鞭,他們只是感情好凉唐,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,857評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著霍骄,像睡著了一般台囱。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上读整,一...
    開封第一講書人閱讀 51,679評(píng)論 1 305
  • 那天簿训,我揣著相機(jī)與錄音,去河邊找鬼米间。 笑死强品,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的车伞。 我是一名探鬼主播择懂,決...
    沈念sama閱讀 40,406評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼另玖!你這毒婦竟也來了困曙?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,311評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤谦去,失蹤者是張志新(化名)和其女友劉穎慷丽,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體鳄哭,經(jīng)...
    沈念sama閱讀 45,767評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡要糊,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了妆丘。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片锄俄。...
    茶點(diǎn)故事閱讀 40,090評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖勺拣,靈堂內(nèi)的尸體忽然破棺而出奶赠,到底是詐尸還是另有隱情,我是刑警寧澤药有,帶...
    沈念sama閱讀 35,785評(píng)論 5 346
  • 正文 年R本政府宣布毅戈,位于F島的核電站苹丸,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏苇经。R本人自食惡果不足惜赘理,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,420評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望扇单。 院中可真熱鬧商模,春花似錦、人聲如沸蜘澜。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽兼都。三九已至,卻和暖如春稽寒,著一層夾襖步出監(jiān)牢的瞬間扮碧,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評(píng)論 1 271
  • 我被黑心中介騙來泰國(guó)打工杏糙, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留慎王,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,298評(píng)論 3 372
  • 正文 我出身青樓宏侍,卻偏偏與公主長(zhǎng)得像赖淤,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子谅河,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,033評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容