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;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
本题要求合并两个有序链表。对于链表中的每一个节点,由于链表是有序的,所以可以将两个链表中的节点按照大小顺序进行比较,然后逐个将较小的节点链接上去,最终得到一个新的有序链表。 使用Rust语言实现这个问题,需要首先定义一个链表节点的结构体,包含node值以及next指针。然后定义一个函数来合并两个有序链表,输入为两个链表的头节点指针,输出为新的有序链表的头节点指针。 在合并过程中,首先需要判断两个链表的头节点哪一个较小,将较小的节点作为新链表的头节点,并将该节点的next指针指向递归调用合并函数的结果。递归结束条件为其中一个链表为空,则将另一个链表直接链接到新链表上。 完整代码如下: ```rust // 定义链表节点结构体 #[derive(Debug)] struct ListNode { val: i32, next: Option<Box<ListNode>>, } impl ListNode { fn new(val: i32) -> Self { ListNode { val, next: None } } } // 合并两个有序链表 fn merge_two_lists(l1: Option<Box<ListNode>>, l2: Option<Box<ListNode>>) -> Option<Box<ListNode>> { match (l1, l2) { (None, None) => None, // 两个链表均为空 (l1, None) => l1, // 其中一个链表为空,直接返回另一个链表 (None, l2) => l2, (Some(mut l1), Some(mut l2)) => { if l1.val < l2.val { l1.next = merge_two_lists(l1.next, Some(l2)); Some(l1) } else { l2.next = merge_two_lists(Some(l1), l2.next); Some(l2) } } } } // 测试代码 fn main() { let l1 = Some(Box::new(ListNode { val: 1, next: Some(Box::new(ListNode { val: 2, next: Some(Box::new(ListNode { val: 4, next: None, })), })), })); let l2 = Some(Box::new(ListNode { val: 1, next: Some(Box::new(ListNode { val: 3, next: Some(Box::new(ListNode { val: 4, next: None, })), })), })); let merged = merge_two_lists(l1, l2); println!("{:?}", merged); } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值