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

題目#105.從前序與中序遍歷序列構(gòu)造二叉樹

根據(jù)一棵樹的前序遍歷與中序遍歷構(gòu)造二叉樹。

注意:
你可以假設(shè)樹中沒有重復(fù)的元素。

例如,給出

前序遍歷 preorder = [3,9,20,15,7]
中序遍歷 inorder = [9,3,15,20,7]

返回如下的二叉樹:

    3
   / \
  9  20
    /  \
   15   7

題目分析

題中提到,給出兩個數(shù)組分別保存二叉樹的前序遍歷和中序遍歷,如何從前序遍歷和中序遍歷恢復(fù)二叉樹呢?
我們可以拿題中給出的二叉樹分析分析:
對于下面兩個數(shù)組以及二叉樹的前中序遍歷的定義:

前序遍歷 preorder = [3,9,20,15,7]
中序遍歷 inorder = [9,3,15,20,7]
    3
   / \
  9  20
    /  \
   15   7

我們可以分別將前中序遍歷的兩個數(shù)組分為三個部分,分別為根節(jié)點與左右子樹:

前序遍歷 preorder = [3] [9] [20,15,7]
中序遍歷 inorder = [9] [3] [15,20,7]

下面說下為什么這么分:

  • 前序遍歷的根節(jié)點必然是第一個,所以很容易將根節(jié)點找到
    得到根節(jié)點在中序遍歷中的索引index
  • 中序遍歷中,根節(jié)點在左右子樹中間,所以根據(jù)中序遍歷,我們能得到左右子節(jié)點的長度
    [9,3,15,20,7] -> [9|3|15,20,7]
    那么左子樹的長度為index - 0,右子樹的長度為inorder.lastIndex - index

構(gòu)建二叉樹

上面的分析幫我們將數(shù)組分為了左右子樹和根節(jié)點,我們得到了左右子樹和新的左右子樹區(qū)間,遞歸就呼之欲出了。

遞歸已經(jīng)使我們的老熟人了,同樣還是考慮兩點:

  • 遞歸結(jié)束條件
    顯然,數(shù)組中沒有元素的時候,需要我們返回的二叉樹就是null,那么我們可以將數(shù)組的是否有元素作為遞歸結(jié)束條件。為了避免數(shù)組的頻繁賦值導(dǎo)致程序效率低下,我們使用數(shù)組和左右index的形式給出一個數(shù)組范圍如a,b分別代表前序數(shù)組的左右范圍,c,d分別代表中序數(shù)組的左右范圍,于是,遞歸結(jié)束條件可以寫為:if (a > b) return null
  • 遞歸體
    既然要構(gòu)造TreeNode,那就得給root賦值左右節(jié)點和根節(jié)點
    • 根節(jié)點
      val root = TreeNode(preorder[a])
    • 左右子節(jié)點
      root.left = buildTree(preorder, aLeft, bLeft, inorder, cLeft, dLeft)
      root.right = buildTree(preorder, aRight, bRight, inorder, cRight, dRight)
      aLeft,bLeft等這些值按照上面的分析,可以很簡單求得。

最終代碼

class Solution {
    fun buildTree(preorder: IntArray, inorder: IntArray): TreeNode? {
        return buildTree(preorder, 0, preorder.lastIndex, inorder, 0, inorder.lastIndex)
    }

    private fun buildTree(preorder: IntArray, a: Int, b: Int, inorder: IntArray, c: Int, d: Int): TreeNode? {
        if (a > b) return null
        val root = TreeNode(preorder[a])
        val index = inorder.indexOf(preorder[a])
        val countLeft = index - c
        val countRight = d - index
        root.left = buildTree(preorder, a + 1, a + countLeft, inorder, c, c + countLeft - 1)
        root.right = buildTree(preorder, b - countRight + 1, b, inorder, d - countRight + 1, d)
        return root
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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

  • 樹形結(jié)構(gòu) 在前面章節(jié)中介紹到的數(shù)據(jù)結(jié)構(gòu),都為線性結(jié)構(gòu),比如鏈表,數(shù)組,隊列等,都屬于線性結(jié)構(gòu),類似于通過一根線串在...
    ducktobey閱讀 1,270評論 0 0
  • 樹的定義與基本術(shù)語 ??樹型結(jié)構(gòu)是一類重要的非線性數(shù)據(jù)結(jié)構(gòu),其中以樹和二叉樹最為常用,是以分支關(guān)系定義的層次結(jié)構(gòu)。...
    java技術(shù)分享師閱讀 1,127評論 0 1
  • 與數(shù)組和鏈表不同,二叉樹有幾種遍歷方式。遍歷算法大致分為深度優(yōu)先和廣度優(yōu)先遍歷算法,這取決于算法實際如何工作。顧名...
    4553675200ad閱讀 1,564評論 0 1
  • 每個人的性格都不同,每個人的性格都代表著不一樣的色彩。那么,性格色彩在生活相處當(dāng)中又是什么樣呢? 在幾千年以前,偉...
    star___閱讀 565評論 0 3
  • 數(shù)據(jù)庫中都會有存儲引擎的概念,MySQL的特點就是其存儲引擎支持插件式的,存儲引擎用來處理數(shù)據(jù)庫相關(guān)的CRUD操作...
    Coding小聰閱讀 325評論 0 0