LeetCode 扁平化多项级双向链表(递归、辅助stack)

您将获得一个双向链表,除了下一个和前一个指针之外,它还有一个子指针,可能指向单独的双向链表。这些子列表可能有一个或多个自己的子项,依此类推,生成多级数据结构,如下面的示例所示。

扁平化列表,使所有结点出现在单级双链表中。您将获得列表第一级的头部。
示例:

输入:
 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

以上示例的说明:
给出以下多级双向链表:
在这里插入图片描述
我们应该返回如下所示的扁平双向链表:
在这里插入图片描述
思路分析:不难发现,当head存在child时,优先访问child(递归),访问完child需要回到head的next。明显的不要不要的递归访问,所以采取stack进行辅助。

/*
// Definition for a Node.
class Node {
public:
    int val;
    Node* prev;
    Node* next;
    Node* child;

    Node() {}

    Node(int _val, Node* _prev, Node* _next, Node* _child) {
        val = _val;
        prev = _prev;
        next = _next;
        child = _child;
    }
};
*/
class Solution {
public:
    Node* flatten(Node* head) {
        stack<Node*> myStack;//辅助队列,当当前head存在child时,保存head->next的现场
        //resListHead结果链表的头部,resListEnd结果链表的尾部
        Node *resListHead = head, *resListEnd = head;
        if (head == NULL){
            return resListHead;
        }
        //第一个节点特殊处理
        if (head->child != NULL){
            //当前head存在child。需要保存head->next的现场
            if (head->next != NULL){
                myStack.push(head->next);
            }
            head = head->child;//并且转移到child
            resListEnd->child = NULL;//结果链表节点所有的child指针域都得置空
        }
        else{
            head = head->next;//否则直接转入到next
        }
        //循环处理剩余的节点
        while (head != NULL || !myStack.empty()){
            if (head == NULL){//如果当前已经到达了某个子链的尾端
                head = myStack.top();//恢复上次保存的next现场
                myStack.pop();
            }
            //将head链接到resListEnd的尾部
            head->prev = resListEnd;
            resListEnd->next = head;
            resListEnd = resListEnd->next;
            //分head是否有child转移到不同的现场
            if (head->child != NULL){
                //当前head存在child。需要保存head->next的现场
                if (head->next != NULL){
                    myStack.push(head->next);
                }
                //转移现场至head的child
                head = head->child;
                resListEnd->child = NULL;//结果链表节点所有的child指针域都得置空
            }
            else{//不存在child,直接访问
                head = head->next;//转移现场至head的next
            }
        }
        //!!!最后需要封尾
        if (resListEnd != NULL){
            resListEnd->next = NULL;
        }
        return resListHead;
    }
};

在这里插入图片描述
方法二:直接递归扁平化。

/*
// Definition for a Node.
class Node {
public:
    int val;
    Node* prev;
    Node* next;
    Node* child;

    Node() {}

    Node(int _val, Node* _prev, Node* _next, Node* _child) {
        val = _val;
        prev = _prev;
        next = _next;
        child = _child;
    }
};
*/
class Solution {
public:
    Node* flatten(Node* head) {
        if (head == NULL){
            return NULL;
        }
        Node *startHeadNext = NULL, *startChild = head;
        //第一步:寻找到第一个有child的节点
        while (startChild != NULL && startChild ->child == NULL){
            startChild = startChild->next;
        }
        if (startChild == NULL){//如果此段链表都没child,直接返回
            return head;
        }
        //第二步:递归扁平化startChild的next
        startHeadNext = flatten(startChild->next);
        startChild->next = NULL;
        //第三步:然后扁平化startChild的child
        Node *startHeadChild = flatten(startChild->child);
        //第四步:将startHeadChild连接到startChild的尾部
        startChild->next = startHeadChild;
        startHeadChild->prev = startChild;
        startChild->child = NULL;
        //第五步:将startHeadNext连接到startChild的尾部
        if (startHeadNext != NULL){
            Node *nowHeadTail = getTail(startChild);//获取startChild的尾部节点
            startHeadNext->prev = nowHeadTail;
            nowHeadTail->next = startHeadNext;
        }
        return head;
    }
    //返回head链表的尾部节点
    Node *getTail(Node *head){
        while (head != NULL && head->next != NULL){
            head = head->next;
        }
        return head;
    }
};

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_41855420/article/details/88774556