1. 程式人生 > 實用技巧 >LeetCode 100. 相同的樹 | Python

LeetCode 100. 相同的樹 | Python

100. 相同的樹


題目來源:力扣(LeetCode)https://leetcode-cn.com/problems/same-tree

題目


給定兩個二叉樹,編寫一個函式來檢驗它們是否相同。

如果兩個樹在結構上相同,並且節點具有相同的值,則認為它們是相同的。

示例 1:

輸入:       1         1
          / \       / \
         2   3     2   3

        [1,2,3],   [1,2,3]

輸出: true

示例 2:

輸入:      1          1
          /           \
         2             2

        [1,2],     [1,null,2]

輸出: false

示例 3:

輸入:       1         1
          / \       / \
         2   1     1   2

        [1,2,1],   [1,1,2]

輸出: false

解題思路


由題意可知,若兩個二叉樹相同,那麼兩個樹在結構上相同,並且節點具有相同的值。那麼,我們可以通過深度優先搜尋(DFS)、廣度優先搜尋(BFS)去判斷兩個二叉樹是否相同。

思路:DFS、BFS

深度優先搜尋(DFS)

使用深度優先搜尋,遇到的情況及分析如下:

  • 當兩個二叉樹都空時,那麼可以判定兩個二叉樹相同,返回 True;
  • 當兩個二叉樹其中一個為空,而另外一個不為空時,那麼兩個二叉樹一定不同的,返回 False;
  • 當兩個二叉樹都不為空的情況下,要對節點的值進行判斷。分別對兩個二叉樹的根節點,以及根節點的左右子樹的值進行判斷。若出現不同,則表示兩個二叉樹不同,返回 False,否則返回 True。

具體的程式碼見【程式碼實現 # 深度優先搜尋】

廣度優先搜尋(BFS)

同樣的,我們也可以使用廣度優先搜尋的方法來解決這個問題,這裡我們要藉助輔助佇列,演算法具體的過程如下:

  • 判斷兩個二叉樹是否同時為空,若是,返回 True;
  • 判斷兩個二叉樹是否其中一個為空,另一個不為空,若是,返回 False;
  • 當兩個二叉樹都不為空時,開始廣度優先搜尋,這裡使用佇列,分別儲存兩個二叉樹的節點:
    • 初始先將兩個二叉樹的根節點分別放入佇列中;
    • 出隊,對出隊的兩個節點的值進行比較:
      • 當兩個節點值不同,那麼二叉樹一定不同;
      • 當兩個節點值相同,繼續判斷二叉樹的結構是否相同,也就是當前節點的子節點是否存在為空的情況。同時為空,判定為相同,但當兩個節點的子節點僅有一個為空,那麼二叉樹不同。
      • 當兩個節點值相同,結構也相同時,將兩個節點的非空子節點分別存入佇列中。這裡需要注意的是,儲存時,如果子節點不為空,那麼考慮的順序都為從左到右。

當前面的演算法執行結束後,如果佇列都為空,那麼表示兩個二叉樹是相同的;如果佇列不都為空,那麼表明二叉樹的結構不同,也就是說兩個二叉樹不同。

具體的程式碼見【程式碼實現 # 廣度優先搜尋】

程式碼實現


# 深度優先搜尋
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def isSameTree(self, p: TreeNode, q: TreeNode) -> bool:
        
        def dfs(p, q):
            # 兩個二叉樹都為空的情況
            if p == None and q == None:
                return True
            # 兩個二叉樹只有一個為空的情況
            elif p == None or q == None:
                return False
            # 二叉樹都不為空的情況,比較值
            elif p.val == q.val:
                # 當根節點的值相同時,往下繼續判斷左右子樹的值
                return dfs(p.left, q.left) and dfs(p.right, q.right)
            # 值不同,返回 False
            return False
            

        return dfs(p, q)

# 廣度優先搜尋
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def isSameTree(self, p: TreeNode, q: TreeNode) -> bool:
        from collections import deque
        # 判斷兩個二叉樹是否為空的情況
        if not p and not q:
            return True
        elif not p or not q:
            return False
        # 都不為空的情況,使用佇列,儲存二叉樹的節點
        # 先將兩個根節點入隊
        queue_p = deque([p])
        queue_q = deque([q])

        while queue_p and queue_q:
            node_p = queue_p.popleft()
            node_q = queue_q.popleft()
            
            # 比較值
            if node_p.val != node_q.val:
                return False
            # 比較結構
            left_p, right_p = node_p.left, node_p.right
            left_q, right_q = node_q.left, node_q.right
            # 這裡使用異或,直接判斷兩個為空以及其中一個為空的情況
            # ^ 相同返回 0,否則返回 1
            # 只有返回 1 的情況才會執行語句,也就是不同返回 False
            if (not left_p) ^ (not left_q):
                return False
            if (not right_p) ^ (not right_q):
                return False
            # 值與結構相同時,當子節點非空,將子節點按照從左到右的順序入隊
            if left_p:
                queue_p.append(left_p)
            if right_p:
                queue_p.append(right_p)
            if left_q:
                queue_q.append(left_q)
            if right_q:
                queue_q.append(right_q)
        
        # 最後需要判斷佇列是否為空
        # 如果佇列不都為空,那麼表明二叉樹結構不同
        return not queue_p and not queue_q

實現結果


歡迎關注


公眾號 【書所集錄