給你二叉樹的根節點 root
,返回其節點值的 層序遍歷 。 (即逐層地,從左到右訪問所有節點)。
示例 1:
輸入:root = [3,9,20,null,null,15,7]
輸出:[[3],[9,20],[15,7]]
示例 2:
輸入:root = [1]
輸出:[[1]]
示例 3:
輸入:root = []
輸出:[]
提示:
樹中節點數目在範圍 [0, 2000] 內
-1000 <= Node.val <= 1000
【分析】
方法一:迭代實現
廣度優先遍歷是按照層層推進的方式,遍歷每一層的節點。題目要求的是返回每一層的節點值,所以這道題非常適合用廣度優先來做。
廣度優先需要用隊列作爲輔助結構,我們先將根結點放到隊列中,然後不斷遍歷隊列。
首先拿出根節點,如果左子樹/右子樹不爲空,就將他們也都放入隊列中。第一遍處理完後,根節點已經從隊列中拿走了,而根節點的兩個孩子已放入隊列中,現在隊列中就有了兩個節點2和5。
第二層處理會將2和5這兩個節點從隊列中拿走,然後再將2和5的子節點放入隊列中,現在隊列中就有三個節點3,4,6。
我們把每一層遍歷到的節點都放入到一個結果集中,最後返回這個結果就可以了。
時間複雜度:O(n)
空間複雜度:O(n)
# 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 levelOrder(self, root: TreeNode) -> List[List[int]]: if not root: return [] res = [] queue = [root] while queue: # 獲取當前隊列的長度,這個長度相當於當前這一層的節點個數 size = len(queue) tmp = [] # 定義臨時列表,用於 # 將隊列中的元素都拿出來(也就是獲取這一層的節點),放到臨時list中 # 如果節點的左子樹/右子樹不爲空,也放入隊列中 for _ in range(size): r = queue.pop(0) tmp.append(r.val) if r.left: queue.append(r.left) if r.right: queue.append(r.right) # 將臨時列表tmp加入最終的返回結果中 res.append(tmp) return res
方法二:遞歸實現
用廣度優先處理是很直觀的,可以想象成是一把刀橫着切割了樹的每一層。
但是深度優先遍歷就不那麼直觀了。我們開下腦洞,把二叉樹的樣子調整一下,擺成一個田字形的樣子。田字形的每一層就對應一個list。
按照深度優先的處理順序,會先訪問節點1,再訪問節點2,接着是節點3。
之後是第二列的節點4,5。最後是第三列的節點6。
每次遞歸的時候都需要帶一個index(表示當前的層數),也就對應那個田字格子中的第幾行,如果當前行對應的list不存在,就加入一個空list進去。
時間複雜度:O(n)
空間複雜度:O(h), h爲樹高度。
class Solution(object): def levelOrder(self, root): """ :type root: TreeNode :rtype: List[List[int]] """ if not root: return [] res = [] def dfs(index,r): # 假設res是[ [1],[2,3] ], index是3,就再插入一個空list放到res中 if len(res)<index: res.append([]) # 將當前節點的值加入到res中,index代表當前層,假設index是3,節點值是99 # res是[ [1],[2,3] [4] ],加入後res就變爲 [ [1],[2,3] [4,99] ] res[index-1].append(r.val) # 遞歸的處理左子樹,右子樹,同時將層數index+1 if r.left: dfs(index+1,r.left) if r.right: dfs(index+1,r.right) dfs(1,root) return res