1. 程式人生 > 其它 >[ LeetCode 107 ] N叉樹層序遍歷

[ LeetCode 107 ] N叉樹層序遍歷

每天分享一個LeetCode題目

每天 5 分鐘,一起進步

LeetCode N叉樹層序遍歷,地址: https://leetcode-cn.com/problems/n-ary-tree-level-order-traversal/

樹結點類

class Node(object):
    def __init__(self, val=None, children=[]):
        self.val = val
        self.children = children

N叉樹的特殊性,就是一個結點可能會包含N個結點,所以,每個結點的孩子結點設定為陣列

層序遍歷

層序遍歷對於很多時候,都是面試經常問到的內容。

尤其是這裡有個小點,可能會讓大家咯噔一下,就是對於結點的列印方式。

比如,樹的結構是:

     A
   / | \
  B  C  D
 /|\   / \
E F G H   I

結果列印的方式會有兩種:

一種是普通遍歷,直接列印

另外一種是每個層級中的元素單獨列印,也是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))

可以直接執行哈!