LeetCode 105. 從前序與中序遍歷序列構造二叉樹 | Pyt

else發表於2021-09-09

105. 從前序與中序遍歷序列構造二叉樹


題目來源:

題目


根據一棵樹的前序遍歷與中序遍歷構造二叉樹。

注意:

你可以假設樹中沒有重複的元素。

例如,給出

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

返回如下的二叉樹:

    3
   / 
  9  20
    /  
   15   7

解題思路


思路:遞迴

在這裡,先講一下前序遍歷和中序遍歷的概念。

  • 前序遍歷:首先訪問根節點,然後遍歷左子樹,最後遍歷右子樹。
  • 中序遍歷:首先遍歷左子樹,然後訪問根節點,最後遍歷右子樹。

即是說兩者的遍歷順序分別為:

  • 前序遍歷:根節點 -> 左子樹 -> 右子樹
  • 中序遍歷:左子樹 -> 根節點 -> 右子樹

根據上面的順序可以看到,前序遍歷中,第一個就是根節點;而中序遍歷中,根節點的左側是左子樹,右側是右子樹。根據這個特性,先結合例子看下。

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

在這個例子當中,前序遍歷 preorder 的第一個元素 3 即是根節點,再看中序遍歷, inorder 中 3 的左邊 [9] 即是左子樹,而右邊 [15, 20, 7] 即是右子樹。根據這個思路,就能構造出完整的二叉樹。

這裡說下具體的思路:

  • 首先找到根節點(依據:前序遍歷順序,先遍歷根節點)
  • 構建根節點的左子樹(依據:中序遍歷,根節點的左側為左子樹)
  • 構建根節點的右子樹(依據:中序遍歷,根節點的右側為右子樹)

題目中,有個提示:【假設樹中沒有重複的元素】。依據這個提示,我們在前序遍歷中找到的根節點元素,可根據元素值在中序遍歷中定位它的位置。

具體的程式碼實現如下。

程式碼實現


# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def buildTree(self, preorder: List[int], inorder: List[int]) -> TreeNode:
        def build_tree(pre_left, pre_right, in_left, in_right):
            """構建二叉樹

            Args:
                pre_left: 前序遍歷左邊界
                pre_right: 前序遍歷右邊界
                in_left: 後序遍歷左邊界
                in_right: 後序遍歷右邊界
            """
            # 終止條件
            if in_left > in_right:
                return None

            # 根據前序遍歷的順序,第一個元素就是根節點
            pre_root = pre_left
            # 構建根節點
            root = TreeNode(preorder[pre_root])

            # 因為題目提示,假設樹中沒有重複元素
            # 那麼根據根節點的值,在 inorder 中定位
            in_root = inorder.index(root.val)
            # 根據中序遍歷的訪問順序,根節點的左邊即是左子樹,右邊是右子樹
            # 在這裡先得到左子樹節點數目
            size_left_subtree = in_root - in_left
            # 構建左子樹
            # 在這裡中序遍歷根節點左邊部分的節點(不包含根節點),其實就等同於前序遍歷左邊界下一位 + size_left_subtree 個節點
            # 即是 in_left 到 inroot 前一位這部分節點,等同於 pre_left 的下一位開始的 size_left_subtree 個元素
            root.left = build_tree(pre_left+1, pre_left+size_left_subtree, in_left, in_root-1)
            # 構建右子樹
            # 此時中序遍歷根節點右邊部分的節點(不包含根節點),對應前序遍歷左邊界 + 1 + sub_left_subtree 開始到其右邊界
            root.right = build_tree(pre_left+1+size_left_subtree, pre_right, in_root + 1, in_right)

            return root

        size = len(inorder)

        return build_tree(0, size-1, 0, size-1)

實現結果


圖片描述

總結


  • 首先在根據前序遍歷訪問的順序,先找到二叉樹的根節點,構建根節點
  • 因為題目說明可假設無重複元素,那麼可依據上面找到根節點的值,在中序遍歷 inorder 中找到其位置。
  • 依據中序遍歷的訪問順序,可確定當前找到的根節點左側是左子樹,右側部分是右子樹
  • 那麼根據上面分析的情況,遞迴構建左子樹,右子樹。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/2318/viewspace-2825515/,如需轉載,請註明出處,否則將追究法律責任。

相關文章