LeetCode 100. 相同的樹 | Python
阿新 • • 發佈:2020-08-07
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
實現結果
歡迎關注
公眾號 【書所集錄】