[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.html

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.node

Example:git

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

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

Explanation for the above example:github

Given the following multilevel doubly linked list:app

We should return the following flattened doubly linked list:函數

 

這道題給了一個多層的雙向鏈表,讓咱們壓平成爲一層的雙向鏈表,題目中給了形象的圖例,不難理解題意。根據題目中給的例子,咱們能夠看出若是某個結點有下一層雙向鏈表,那麼下一層雙向鏈表中的結點就要先加入進去,若是下一層鏈表中某個結點還有下一層,那麼仍是優先加入下一層的結點,整個加入的機制是DFS的,就是有岔路先走岔路,走到沒路了後再返回,這就是深度優先遍歷的機制。好,那麼既然是DFS,確定優先考慮遞歸啦。方法有了,再來看具體怎麼遞歸。因爲給定的多層鏈表自己就是雙向的,因此咱們只須要把下一層的結點移到第一層便可,那麼沒有子結點的結點就保持原狀,不做處理。只有對於那些有子結點的,咱們須要作一些處理,因爲子結點連接的雙向鏈表要加到後面,因此當前結點以後要斷開,再斷開以前,咱們用變量 next 指向下一個鏈表,而後對子結點調用遞歸函數,咱們 suppose 返回的結點已經壓平了,那麼就只有一層,就至關於要把這一層的結點加到斷開的地方,因此須要知道這層的最後一個結點的位置,咱們用一個變量 last,來遍歷到壓平的這一層的末結點。如今就能夠開始連接了,首先把子結點鏈到 cur 的 next,而後把反向指針 prev 也鏈上。此時 cur 的子結點 child 能夠清空,而後壓平的這一層的末節點 last 鏈上以前保存的 next 結點,若是 next 非空,那麼鏈上反向結點 prev。這些操做完成後,咱們就已經將壓平的這一層完整的加入了以前層斷開的地方,繼續在以前層往下遍歷便可,參見代碼以下:spa

 

解法一:指針

class Solution {
public:
    Node* flatten(Node* head) {
        Node *cur = head;
        while (cur) {
            if (cur->child) {
                Node *next = cur->next;
                cur->child = flatten(cur->child);
                Node *last = cur->child;
                while (last->next) last = last->next;
                cur->next = cur->child;
                cur->next->prev = cur;
                cur->child = NULL;
                last->next = next;
                if (next) next->prev = last;
            }
            cur = cur->next;
        }
        return head;
    }
};

 

咱們其實也能夠不用遞歸,鏈表的題不像樹的題,對於樹的題使用遞歸能夠很簡潔,而鏈表遞歸和迭代可能差的並很少。若是你仔細對比兩種方法的代碼,你會發現迭代的寫法恰好比遞歸的寫法少了調用遞歸的那一行,給人一種徹底沒有必要使用遞歸的感受,其實兩種解法的操做順序不一樣的,遞歸寫法是從最底層開始操做,先把最底層加入倒數第二層,再把混合後的層加入倒數第三層,依此類推,直到都融合到第一層爲止。而迭代的寫法倒是反過來的,先把第二層加入第一層,此時第二層底下可能還有不少層,沒必要理會,以後等遍歷到的時候,再一層一層的加入第一層中,無論哪一種方法,最終均可以壓平,參見代碼以下:code

 

解法二:htm

class Solution {
public:
    Node* flatten(Node* head) {
        Node *cur = head;
        while (cur) {
            if (cur->child) {
                Node *next = cur->next;
                Node *last = cur->child;
                while (last->next) last = last->next;
                cur->next = cur->child;
                cur->next->prev = cur;
                cur->child = NULL;
                last->next = next;
                if (next) next->prev = last;    
            }
            cur = cur->next;
        }
        return head;
    }
};

 

Github 同步地址:

https://github.com/grandyang/leetcode/issues/430

 

相似題目:

Flatten Binary Tree to Linked List

 

參考資料:

https://leetcode.com/problems/flatten-a-multilevel-doubly-linked-list/

https://leetcode.com/problems/flatten-a-multilevel-doubly-linked-list/discuss/137649/Simple-Java-Solution

https://leetcode.com/problems/flatten-a-multilevel-doubly-linked-list/discuss/152066/c%2B%2B-about-10-lines-solution

 

LeetCode All in One 題目講解彙總(持續更新中...)

相關文章
相關標籤/搜索