leetcode430 扁平化多级双向链表

我的方法是用DFS 一开始想直接在head链表的基础上进行修改
结果发现单纯的dfs不行,因为当遍历的有子节点的结点时可以改变这两个结点间的链接关系,但是当一个分支全部遍历完毕之后,还要回到上一级,就是上个有孩子结点的那个结点的后一个结点,所以就需要把这些需要结点都要保存下来,有2个结点就要保存2个,有100个结点就要保存100个但从传递参数的角度来看,是不现实的。理论上可以传递一个栈的指针,用栈来保存这些结点,但一个分支结束时,弹出栈顶指针就可以

实际上采用的方法是dfs遍历每个结点然后加入到新的链表中。注意到此链表是没有头结点的单链表,同时要注意传递到函数中的指针的参数

用二级指针

class Solution {
public:
    void dfs(Node* tail,Node** anstail,Node** anshead)
    { 
        if(tail==NULL)
        return; 
        Node* temp=(Node*)malloc(sizeof(Node));
        temp->val=tail->val;
        temp->next=NULL;
        temp->prev=NULL;
        temp->child=NULL;
        //插入到tail的后面
        if((*anstail)==NULL)
        {
            //没有头结点的链表的尾插法需要注意下面两行特别是
            //head指针的赋值
            (*anstail)=temp;
            (*anshead)=(*anstail);
        }
        else
        {
            (*anstail)->next=temp;
            temp->prev=*anstail;
            (*anstail)=(*anstail)->next;
        }


        if(tail->child!=NULL)
        {
            dfs(tail->child,anstail,anshead);
        }
        dfs(tail->next,anstail,anshead);

    }
    Node* flatten(Node* head) {
        Node* anshead=NULL;
        Node* anstail=anshead;
        dfs(head,&anstail,&anshead);
        return anshead;
    }
};

用引用

class Solution {
public:
    void dfs(Node* tail,Node* &anstail,Node* &anshead)
    { 
        if(tail==NULL)
        return; 
        Node* temp=(Node*)malloc(sizeof(Node));
        temp->val=tail->val;
        temp->next=NULL;
        temp->prev=NULL;
        temp->child=NULL;
        //插入到tail的后面
        if(anstail==NULL)
        {
            
            anstail=temp;
            anshead=anstail;
        }
        else
        {
            anstail->next=temp;
            temp->prev=anstail;
            anstail=anstail->next;
        }


        if(tail->child!=NULL)
        {
            dfs(tail->child,anstail,anshead);
        }
        dfs(tail->next,anstail,anshead);

    }
    Node* flatten(Node* head) {
        Node* anshead=NULL;
        Node* anstail=anshead;
        dfs(head,anstail,anshead);
        return anshead;
    }
};

题解中可用dfs函数的返回值来标记一个分支的最后一个结点来解决原址修改的问题

class Solution {
public:
    Node* dfs1(Node* p)
    {
        if(p==NULL)
        return NULL;
        if(p->next==NULL&&p->child==NULL)
        return p;
        if(p->child!=NULL)
        {
           Node* last1=dfs1(p->child);
           Node* q=p->next;
           p->next=p->child;
           p->next->prev=p;
           p->child=NULL;
           if(q!=NULL)
           {
              last1->next=q;
              q->prev=last1;
              return dfs1(q);
           }
           else
              return last1;
        }
        else
            return dfs1(p->next);
    }
    Node* flatten(Node* head) {
        dfs1(head);
        return head;
    }
};

官方的显然要更好一些

class Solution {
public:
    Node* flatten(Node* head) {
        function<Node*(Node*)> dfs = [&](Node* node) {
            Node* cur = node;
            Node* last = nullptr;
            while (cur) {
                Node* next = cur->next;
                if (cur->child) {
                    Node* child_last = dfs(cur->child);
                    next = cur->next;
                    cur->next = cur->child;
                    cur->child->prev = cur;
                    if (next) {
                        child_last->next = next;
                        next->prev = child_last;
                    }
                    cur->child = nullptr;
                    last = child_last;
                }
                else {
                    last = cur;
                }
                cur = next;
            }
            return last;
        };

        dfs(head);
        return head;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值