昨天接觸了二叉樹中的前中後三序遍歷的代碼實現,今天來看剩下的那種層序遍歷。
題目一
第 102 題:二叉樹的層序遍歷
難度:中等
給你一個二叉樹,請你返回其按 層序遍歷 得到的節點值。 (即逐層地,從左到右訪問所有節點)。
示例:
二叉樹:[3,9,20,null,null,15,7],
3
/ \
9 20
/ \
15 7
返回其層次遍歷結果:
[
[3],
[9,20],
[15,7]
]
題目分析
看其輸出格式,是將二叉樹每層的節點放到單獨的列表中,而代碼輸入的是 root 根節點,要通過 root.left 取左子節點、root.right 取其右節點。那麼可以每次都提取同一層的節點記錄在同一列表中,遍歷列表、取列表中節點的子節點,繼續將結果放入同一列表中,直到最後一層。
代碼實現
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def levelOrder(self, root: TreeNode) -> List[List[int]]:
# 如果根節點非空,其放入層列表中
if root!=None:
level = [root]
# 若根節點空,保持列表爲空,最終直接返回
else:
level = []
# 用來記錄結果的列表
result = []
# 當層列表非空時
while level:
# 將層列表中的節點值組成列表存入結果中
result.append([ item.val for item in level if item!=None])
# 新的層列表
new_level = []
# 遍歷當前層列表
for node in level:
# 如果左子節點非空
if node.left!=None:
# 將左子節點加入到新的層列表中
new_level.append(node.left)
# 同理處理右子節點
if node.right!=None:
new_level.append(node.right)
# 將新的子節點賦給層列表,帶入下次循環
level = new_level
# 返回結果列表
return result
提交測試表現:
執行用時 : 48 ms, 在所有 Python3 提交中擊敗了 37.30% 的用戶
內存消耗 : 14.1 MB, 在所有 Python3 提交中擊敗了 7.14% 的用戶
原本想參考題解優化的,後來發現題解中提到的“廣度優先搜索”方法下的代碼邏輯與我們的代碼基本相同。
廣度優先搜索算法(英語:Breadth-First Search,縮寫爲BFS),又譯作寬度優先搜索,或橫向優先搜索,是一種圖形搜索算法。簡單的說,BFS是從根節點開始,沿着樹的寬度遍歷樹的節點。如果所有節點均被訪問,則算法中止。
維基百科-廣度優先搜索
挺開心的,可以獨立做出二叉樹的題了!
題目二
面試題 檢查平衡性
難度:簡單
實現一個函數,檢查二叉樹是否平衡。在這個問題中,平衡樹的定義如下:任意一個節點,其兩棵子樹的高度差不超過 1。
示例 1:
給定二叉樹 [3,9,20,null,null,15,7]
3
/ \
9 20
/ \
15 7
返回 true 。
示例 2:
給定二叉樹 [1,2,2,3,3,null,null,4,4]
1
/ \
2 2
/ \
3 3
/ \
4 4
返回 false 。
#來源:力扣(LeetCode)
#鏈接:https://leetcode-cn.com/problems/check-balance-lcci
題目分析
這雖然標着個簡單題,考慮半天沒有頭緒,想着如果通過層序遍歷這二叉樹,給每層節點記錄高度,但越想就越複雜了。學習下題解裏的優秀解法吧!
這裏直接貼代碼來學習:
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
# 這裏相當於定義了個全局變量
def __init__(self):
self.flag = True
def isBalanced(self, root: TreeNode) -> bool:
# 定義獲取節點高度的函數,之後遞歸調用
def isb(root):
# 空節點,返回高度 0
if not root:
return 0
# 由左子樹可計算出的高度=左子樹高度+1
l = isb(root.left) + 1
# 由右子樹計算的高度 = 右子樹高度+1
r = isb(root.right) + 1
# 若左右子樹高度差大於1
if abs(l-r)>1:
# 將全局的平衡狀態改爲 False
self.flag = False
# 返回左右計算的最大高度
return max(l,r)
# 由根節點開始執行函數
isb(root)
# 返回最終的平衡狀態
return self.flag
#作者:skyyou-dang
#鏈接:https://leetcode-cn.com/problems/check-balance-lcci/solution/she-zhi-yi-ge-bian-liang-bao-cun-xia-mou-ge-jie-di/
原以爲會是比較簡單直接的計算高度方法,沒想到用到了遞歸,以及通過 init 中定義初始屬性實現了全局變量的作用。我嘗試着去掉這個 init 中對 flag 的定義與使用,換成函數內的變量會麻煩很多。對類、方法、屬性這些通過題目也有比較多接觸,之後也要專門系統整理下相關內容。
這個解法思路,贊,多消化消化。
題目三
第 226 題:翻轉二叉樹
難度:簡單
翻轉一棵二叉樹。
示例 1:
輸入:
4
/ \
2 7
/ \ / \
1 3 6 9
示例 2:
輸出:
4
/ \
7 2
/ \ / \
9 6 3 1
#來源:力扣(LeetCode)
#鏈接:https://leetcode-cn.com/problems/invert-binary-tree
題目分析
解法一:
看到這題,首先想到的還是遍歷每個節點,然後將其左右子節點對調就可以了。遍歷的過程還是用我們第一題裏設計的層級遍歷,應該就能一遍過。
代碼實現
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def invertTree(self, root: TreeNode) -> TreeNode:
# 空節點單獨處理下
if root ==None:
return None
# 層列表
level = [root]
# 層列表不爲空,循環
while level:
# 裝子節點的新列表
new_level = []
# 遍歷層列表中的節點
for item in level:
# 對調左右子節點位置
item.left,item.right = item.right,item.left
# 若左子節點非空
if item.left:
# 加入到新列表中
new_level.append(item.left)
# 新列表添加非空右子節點
if item.right:
new_level.append(item.right)
# 層列表更新爲新記錄的子節點列表,進入下一層循環
level = new_level
# 對調完所有的,返回根節點
return root
提交測試表現:
執行用時 : 36 ms, 在所有 Python3 提交中擊敗了 80.20% 的用戶
內存消耗 : 13.7 MB, 在所有 Python3 提交中擊敗了 5.26% 的用戶
解法二
難得發現一道可以自己壯着膽子用遞歸的題目,既然是要翻轉二叉樹,那麼翻轉子樹完全可以通過遞歸調用自身來實現,翻轉完兩子樹,再將兩子節點翻轉即可!
代碼一氣呵成:
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def invertTree(self, root: TreeNode) -> TreeNode:
# 空節點返回 None
if root==None:
return None
# 遞歸翻轉左子樹
self.invertTree(root.left)
# 遞歸翻轉右子樹
self.invertTree(root.right)
# 交換左右子節點
root.left, root.right = root.right,root.left
# 返回根節點
return root
提交測試表現:
執行用時 : 40 ms, 在所有 Python3 提交中擊敗了 61.62% 的用戶
內存消耗 : 13.7 MB, 在所有 Python3 提交中擊敗了 5.26% 的用戶
結論
今天遇到的二叉樹題目,要麼是基於層序遍歷,要麼是基於遞歸實現,做起來也有豁然開朗的感覺。
二叉樹初接觸可能會不知所云,慢慢摸索規律還是挺有意思的。加上昨天,我們練習了五道 LeetCode 關於二叉樹的題目(外加一道面試題目),明天先告一段落、繼續換個專題練習。