二叉樹(shù) 16 (從前序與后序遍歷序列構(gòu)造二叉樹(shù) leetcode 889)

思想

二叉樹(shù)的核心思想是分治和遞歸粤铭,特點(diǎn)是遍歷方式。
解題方式常見(jiàn)兩類思路:

  1. 遍歷一遍二叉樹(shù)尋找答案啃洋;
  2. 通過(guò)分治分解問(wèn)題尋求答案霞怀;

遍歷分為前中后序遍希,本質(zhì)上是遍歷二叉樹(shù)過(guò)程中處理每個(gè)節(jié)點(diǎn)的三個(gè)特殊時(shí)間點(diǎn):

  1. 前序是在剛剛進(jìn)入二叉樹(shù)節(jié)點(diǎn)時(shí)執(zhí)行;
  2. 后序是在將要離開(kāi)二叉樹(shù)節(jié)點(diǎn)時(shí)執(zhí)行里烦;
  3. 中序是左子樹(shù)遍歷完進(jìn)入右子樹(shù)前執(zhí)行;
# 前序
     1 node
    /      \
 2 left   3 right
中左右
 
# 中序
     2 node
    /      \
 1 left    3 right
左中右
 
# 后序
     3 node
    /      \
 1 left    2 right     
左右中       

多叉樹(shù)只有前后序列遍歷禁谦,因?yàn)橹挥卸鏄?shù)有唯一一次中間節(jié)點(diǎn)的遍歷

題目的關(guān)鍵就是找到遍歷過(guò)程中的位置胁黑,插入對(duì)應(yīng)代碼邏輯實(shí)現(xiàn)場(chǎng)景的目的。

實(shí)例

從前序與后序遍歷序列構(gòu)造二叉樹(shù) leetcode 889

class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

輸入:
(1)preorder: List[int]州泊,前序遍歷整數(shù)數(shù)組
(2)postorder: List[int]丧蘸,后序遍歷整數(shù)數(shù)組

輸出:
TreeNode,根據(jù)兩個(gè)遍歷數(shù)組構(gòu)建一顆二叉樹(shù)遥皂,返回根節(jié)點(diǎn)力喷。

舉例:
給定 preorder = [1,2,4,5,3,6,7], postorder = [4,5,2,6,7,3,1]
返回二叉樹(shù) [1,2,3,4,5,6,7]

    1                 
   / \               
 2    3         
/ \  / \          
4 5  6  7        

二叉樹(shù)的數(shù)據(jù)存儲(chǔ)可以使用鏈表,也可以使用數(shù)組演训,往往數(shù)組更容易表達(dá)弟孟,根節(jié)點(diǎn)從 index=1 處開(kāi)始存儲(chǔ),浪費(fèi) index=0 的位置
left_child = 2 * parent
right_child = 2 * parent + 1
parent = child // 2

分治解

基本情境是找到當(dāng)前構(gòu)建二叉樹(shù)的根節(jié)點(diǎn)和左右子樹(shù)样悟,要利用前序和后序遍歷的特點(diǎn)拂募。
根節(jié)點(diǎn)很容易獲得庭猩,就是前序遍歷當(dāng)前范圍的第一個(gè)元素,因?yàn)榍靶虮闅v是最先遍歷當(dāng)前節(jié)點(diǎn)的陈症。

# 前序
root.val | root.left (left_root, ...) | root.right (right_root, ...)

# 后序
root.left (..., left_root) | root.right (..., right_root) | root.val

接著在前序當(dāng)前根節(jié)點(diǎn)的下一個(gè)位置獲得左子樹(shù)的根節(jié)點(diǎn)蔼水,接著在后序中尋找對(duì)應(yīng)元素的位置(題目中沒(méi)有重復(fù)的元素),這樣就發(fā)現(xiàn)了左右子樹(shù)的索引邊界录肯。

編碼


from typing import Optional, List


class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right


def construct_binary_tree_from_preorder_and_postorder_traversal(preorder: List[int], postorder: List[int]) -> Optional[
    TreeNode]:
    # 記錄后序的元素下標(biāo)
    postorder_dict = {}

    def build(preorder: List[int], prestart: int, preend: int, postorder: List[int], poststart: int, postend: int) -> Optional[TreeNode]:
        # base 條件趴腋,返回樹(shù)子葉的左右 
        if prestart > preend:
            return None
        if prestart == preend:
            return TreeNode(preorder[prestart])
        # 獲取 root 和左右子樹(shù)范圍
        root_val = preorder[prestart]
        partition_index = postorder_dict[preorder[prestart + 1]]
        size = partition_index - poststart + 1
        # 構(gòu)建樹(shù)
        root = TreeNode(root_val)
        root.left = build(preorder, prestart + 1, prestart + size, postorder, poststart, partition_index)
        root.right = build(preorder, prestart + size + 1, preend, postorder, partition_index + 1, postend - 1)
        return root

    # 獲取后序的元素下標(biāo)位置
    for i in range(len(postorder)):
        postorder_dict[postorder[i]] = i
    return build(preorder, 0, len(preorder) - 1, postorder, 0, len(postorder) - 1)

相關(guān)

二叉樹(shù) 0
二叉樹(shù) 1
二叉樹(shù) 2
二叉樹(shù) 3
二叉樹(shù) 4
二叉樹(shù) 5
二叉樹(shù) 6
二叉樹(shù) 7
二叉樹(shù) 8
二叉樹(shù) 9
二叉樹(shù) 10
二叉樹(shù) 11
二叉樹(shù) 12
二叉樹(shù) 13
二叉樹(shù) 14
二叉樹(shù) 15

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市论咏,隨后出現(xiàn)的幾起案子优炬,更是在濱河造成了極大的恐慌,老刑警劉巖潘靖,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件穿剖,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡卦溢,警方通過(guò)查閱死者的電腦和手機(jī)糊余,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)单寂,“玉大人贬芥,你說(shuō)我怎么就攤上這事⌒觯” “怎么了蘸劈?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)尊沸。 經(jīng)常有香客問(wèn)我威沫,道長(zhǎng),這世上最難降的妖魔是什么洼专? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任棒掠,我火速辦了婚禮,結(jié)果婚禮上屁商,老公的妹妹穿的比我還像新娘烟很。我一直安慰自己,他們只是感情好蜡镶,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布雾袱。 她就那樣靜靜地躺著,像睡著了一般官还。 火紅的嫁衣襯著肌膚如雪芹橡。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,631評(píng)論 1 305
  • 那天望伦,我揣著相機(jī)與錄音僻族,去河邊找鬼粘驰。 笑死,一個(gè)胖子當(dāng)著我的面吹牛述么,可吹牛的內(nèi)容都是我干的蝌数。 我是一名探鬼主播,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼度秘,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼顶伞!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起剑梳,我...
    開(kāi)封第一講書(shū)人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤唆貌,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后垢乙,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體锨咙,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年追逮,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了酪刀。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出掺涛,到底是詐尸還是另有隱情,我是刑警寧澤历涝,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站漾唉,受9級(jí)特大地震影響荧库,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜赵刑,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一电爹、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧料睛,春花似錦、人聲如沸摇邦。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)施籍。三九已至居扒,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間丑慎,已是汗流浹背喜喂。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工瓤摧, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人玉吁。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓照弥,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親进副。 傳聞我的和親對(duì)象是個(gè)殘疾皇子这揣,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

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