天天看點

LeetCode 430:扁平化多級雙向連結清單 Flatten a Multilevel Doubly Linked List

您将獲得一個雙向連結清單,除了下一個和前一個指針之外,它還有一個子指針,可能指向單獨的雙向連結清單。這些子清單可能有一個或多個自己的子項,依此類推,生成多級資料結構,如下面的示例所示。

扁平化清單,使所有結點出現在單級雙連結清單中。您将獲得清單第一級的頭部。

You are given a doubly linked list which in addition to the next and previous pointers, it could have a child pointer, which may or may not point to a separate doubly linked list. These child lists may have one or more children of their own, and so on, to produce a multilevel data structure, as shown in the example below.

Flatten the list so that all the nodes appear in a single-level, doubly linked list. You are given the head of the first level of the list.

示例:

輸入:
 1---2---3---4---5---6--NULL
         |
         7---8---9---10--NULL
             |
             11--12--NULL

輸出:
1-2-3-7-8-11-12-9-10-4-5-6-NULL           

以上示例的說明:

給出以下多級雙向連結清單:

我們應該傳回如下所示的扁平雙向連結清單:

解題思路:

這道題是典型的 DFS(深度優先搜尋)型例題,并且給出了圖解,隻要了解過 DFS 的應該立即就能想到思路。

針對這道題簡單說下:深度優先搜尋 就像一棵樹(二叉樹)的前序周遊,從某個頂點(連結清單頭節點)出發,自頂向下周遊,然後遇到頂點的未被通路的鄰接點(子節點 Child),繼續進行深度優先周遊,重複上述過程(遞歸),直到所有頂點都被通路為止。

其邏輯以示例輸入為例:

1---2---3---4---5---6--NULL
       |
        7---8---9---10--NULL
              |
             11---12---NULL           
從節點 1 開始周遊,目前周遊連結清單為:1---2---3---4---5---6--NULL

遇到鄰接點 2,其子連結清單為:7---8---9---10--NULL
将子連結清單頭節點 7 作為參數傳入 DFS 函數,目前周遊連結清單為:7---8---9---10---NULL

繼續周遊,遇到鄰接點 8,其子連結清單為:11--12--NULL
将子連結清單頭節點 8 作為參數傳入 DFS 函數,目前周遊連結清單為:11--12---NULL

繼續周遊,無鄰接點,周遊結束,傳回目前連結清單尾節點 12
改變鄰接點 8 與子連結清單頭節點 11 關系:7---8---11---12
連接配接傳回值 尾節點 12 和鄰接點的下一個節點 9: 7---8---11---12---9---10---NULL

繼續周遊,無鄰接點,周遊結束,傳回目前連結清單尾節點 10
改變鄰接點 2 與 子連結清單頭節點 7 關系:1---2---7---8---11---12---9---10--NULL
連接配接傳回值 尾節點 10 和鄰接點的下一個節點 3: 1---2---7---8---11---12---9---10---3---4---5---6--NULL

繼續周遊,無鄰接點,周遊結束,傳回目前連結清單尾節點 6

遞歸結束,傳回頭節點 1,連結清單為: 1---2---7---8---11---12---9---10---3---4---5---6--NULL           

Java:

class Solution {
    public Node flatten(Node head) {
        dfs(head);
        return head;
    }
    //深度優先搜尋函數
    private Node dfs(Node head) {
        Node cur = head;
        while (cur != null) {
            if (cur.child != null) {
                //改變目前節點與子節點的關系
                Node next = cur.next;//記錄暫存下一個節點
                cur.next = cur.child;//目前節點與子連結清單頭節點連接配接
                cur.next.prev = cur;
                //傳遞子連結清單頭節點作為參數到 dfs
                Node childLast = dfs(cur.child);//childLast獲得傳回值為子連結清單的尾節點
                childLast.next = next;//子連結清單尾節點與暫存節點連接配接
                if (next != null) next.prev = childLast;//暫存節點不為空就将其prev指向子連結清單尾節點
                cur.child = null;//子連結清單置空
                cur = childLast;//重新整理目前節點,跳過子連結清單的周遊
            }
            head = cur;//頭節點重新整理為目前節點
            cur = cur.next;//重新整理目前節點
        }
        return head;//傳回子連結清單的尾節點
    }
}           

Python3:

class Solution:
    def flatten(self, head: 'Node') -> 'Node':
        self.dfs(head)
        return head

    def dfs(self, head):
        cur = head
        while cur:
            if cur.child:
                next = cur.next
                cur.next = cur.child
                cur.next.prev = cur
                childLast = self.dfs(cur.child)
                childLast.next = next
                if next: next.prev = childLast
                cur.child = None
            head = cur
            cur = cur.next
        return head           

歡迎關注微.信公.衆号:愛寫Bug

繼續閱讀