讀前福利:幾百本互聯網技術書籍送給你們node
天天分享一個LeetCode題目python
天天 5 分鐘,一塊兒進步面試
LeetCode N叉樹層序遍歷,地址: leetcode-cn.com/problems/n-…數組
class Node(object):
def __init__(self, val=None, children=[]):
self.val = val
self.children = children
複製代碼
N叉樹的特殊性,就是一個結點可能會包含N個結點,因此,每一個結點的孩子結點設置爲數組markdown
層序遍歷對於不少時候,都是面試常常問到的內容。app
尤爲是這裏有個小點,可能會讓你們咯噔一下,就是對於結點的打印方式。oop
好比,樹的結構是:post
A
/ | \
B C D
/|\ / \
E F G H I
複製代碼
結果打印的方式會有兩種:ui
一種是普通遍歷,直接打印spa
另一種是每一個層級中的元素單獨打印,也是LeetCode429 要求的格式
# 第一種
['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I']
# 第二種
[['A'], ['B', 'C', 'D'], ['E', 'F', 'G', 'H', 'I']]
複製代碼
第一種很簡單,第二種可能須要一些小小的中間結果記錄,我們分開說說...
1.初始化結果集res,初始化隊列queue,將根結點放置到queue中;
2.只要queue不爲空,循環遍歷,每次遍歷將隊首元素防止到 res 中,以後將隊首元素的孩子結點依次入隊;
3.循環執行第 2 點。
看看代碼:
def levelOrder_basic(self, root):
# 初始化結果集res
res = []
# 初始化隊列queue,將根結點放置到queue中
queue = collections.deque()
queue.appendleft(root)
while(queue):
# 每次遍歷將隊首元素防止到 res 中
pop_node = queue.pop()
res.append(pop_node.val)
# 將隊首元素的孩子結點依次入隊
for node in pop_node.children:
queue.appendleft(node)
return res
複製代碼
其實比較簡單,就是將遍歷到的結點放置到結果集中,同時將結點的孩子結點入隊,以後循環進行就好!
這種遍歷,有一點難處就是要將每一層級的元素單獨放置到數組中,而後將每一層級的數組放置到最後的數組中
這樣:
[['A'], ['B', 'C', 'D'], ['E', 'F', 'G', 'H', 'I']]
複製代碼
相似於 第一種 層序遍歷,須要改變的就是要將每一層級的元素單獨遍歷
1.初始化結果集res,初始化隊列queue,將根結點放置到queue中;
(注意:此處的queue放置的是每一層的結點元素,不理解不要緊,往下看)
2.只要queue不爲空,循環遍歷,同時初始化兩個臨時數組
第一個:tmp_res = [],臨時存放每一層遍歷訪問到的結點,最終會合併到結果res中
第二個:tmp_queue = [],臨時存放下一層的結點元素,用於下一個循環的遍歷
每次遍歷將隊首元素防止到 tmp_res 中,以後將隊首元素的孩子結點依次入隊 tmp_queue
最後,將 tmp_queue 賦值給 queue,tmp_res併入到最終結果集 res
3.循環執行第 2 點,直到 queue 爲空
4.返回最終結果集 res
看代碼
def levelOrder(self, root):
# 最終結果
res = []
if not root:
return res
# 初始化隊列,而且將根結點置入隊列中
# 存放每個層級的結點
queue = collections.deque()
queue.appendleft(root)
while(queue):
# 臨時存放結點的隊列,最終合併到最後的 res 中
tmp_res = []
# 臨時存放下一層結點的隊列
tmp_queue = []
for node in queue:
tmp_res.append(node.val)
# 將孩子結點放置到 tmp_queue 中
for child_node in node.children:
tmp_queue.append(child_node)
# 將 tmp_queue 賦值給 queue,tmp_res併入到最終結果集 res
queue = tmp_queue
res.append(tmp_res)
複製代碼
看着比較複雜,其實關鍵有一點,以前循環遍歷 queue 就好,如今是把每一層結點動態的賦值給 queue,也就是說每一次循環遍歷,queue 中的值是當前層的結點集。
動手畫一畫就會看起來很簡單了哈!
# -*- coding:utf-8 -*-
# !/usr/bin/env python
import collections
# 樹結點類
class Node(object):
def __init__(self, val=None, children=[]):
self.val = val
self.children = children
class Solution(object):
def levelOrder_basic(self, root):
""" 基礎的層序遍歷,就是把每一層的結點值一次性打印出來 相似於 ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I'] 這樣 :param root: :return: """
res = []
queue = collections.deque()
queue.appendleft(root)
while(queue):
pop_node = queue.pop()
res.append(pop_node.val)
for node in pop_node.children:
queue.appendleft(node)
return res
def levelOrder(self, root):
""" 層序遍歷(LeetCode中規定的格式),即把每一層的結點放進各自的數組中 相似於[['A'], ['B', 'C', 'D'], ['E', 'F', 'G', 'H', 'I']] 這樣 :param root: :return: """
# 最終結果
res = []
if not root:
return res
# 初始化隊列,而且將根結點置入隊列中
# 存放每個層級的結點
queue = collections.deque()
queue.appendleft(root)
while(queue):
# 臨時存放結點的隊列,最終合併到最後的 res 中
tmp_res = []
# 臨時存放下一層結點的隊列
tmp_queue = []
for node in queue:
tmp_res.append(node.val)
# 將孩子結點放置到 tmp_queue 中
for child_node in node.children:
tmp_queue.append(child_node)
queue = tmp_queue
res.append(tmp_res)
return res
if __name__ == "__main__":
# 新建節點
root = Node('A')
node_B = Node('B')
node_C = Node('C')
node_D = Node('D')
node_E = Node('E')
node_F = Node('F')
node_G = Node('G')
node_H = Node('H')
node_I = Node('I')
# 構建三叉樹
# A
# / | \
# B C D
# /|\ / \
# E F G H I
root.children = [node_B, node_C, node_D]
node_B.children = [node_E, node_F, node_G]
node_D.children = [node_H, node_I]
s = Solution()
print(s.levelOrder_basic(root))
print(s.levelOrder(root))
複製代碼
能夠直接執行哈!