复杂链表的复制

剑指OFFER题35------按牛客网热度排序

时间:2018.12.16.2114
作者:Waitt

题目

输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)

时间限制:1秒 空间限制:32768K 热度指数:261260

解答

在这里插入图片描述

*解题思路:
*1、遍历链表,复制每个结点,如复制结点A得到A1,将结点A1插到结点A后面;
*2、重新遍历链表,复制老结点的随机指针给新结点,如A1.random = A.random.next;
*3、拆分链表,将链表拆分为原链表和复制后的链表

注意:整个复制过程不仅要复制旧链表,且最终结果不能改变旧链表的值!!!

/*
struct RandomListNode {
    int label;
    struct RandomListNode *next, *random;
    RandomListNode(int x) :
            label(x), next(NULL), random(NULL) {
    }
};
*/
class Solution {
public:
    RandomListNode* Clone(RandomListNode* pHead)
    {
        if(!pHead)
            return NULL;
        RandomListNode* nh=pHead;//新头结点
        RandomListNode* nt=pHead;//新临时节点
        RandomListNode* f=pHead;//中间变量
        while(nt)//将旧链表进行复制
        {
            RandomListNode *t=new RandomListNode(nt->label);//new创建变量空间
            f=nt->next;
            nt->next=t;
            t->next=f;
            nt=f;
        }
        nt=pHead;
        nh=nt->next;
        while(nh)//将旧链表的随机指针赋值给新链表
        {
            if(nt->random)//保证nt->random不是NULL,若nt->random=NULL,则nt->random->next报错
                nh->random=nt->random->next;
            nt=nh->next;
            if(!nt)//保证nt不是NULL
                break;
            nh=nt->next;
        }
        nt=pHead;
        nh=nt->next;//新头结点
        while(nt->next)//将新旧链表拆分,逐个拆分法
        {
            f=nt->next;
            nt->next=f->next;
            nt=f;
        }
        /*每次拆分两个结点方法
        f=nh=nt->next;
        while(f->next)
        {
            nt->next=f->next;
            nt=nt->next;
            f->next=nt->next;
            f=f->next;
        }
        nt->next=f->next;//此题要求极其严格,必须将旧链表复制,且不影响旧链表的值。此处才可完全将旧链表还原
        */
        return nh;
    }
};

注意:频繁使用指针会经常产生NULL->next的bug

容易出现的问题:复制链表必须将新链表复制,且不影响旧链表的值

new的使用:https://www.cnblogs.com/lca1826/p/6506183.html

疑问

vector创建的空间与new创建空间的区别:

以下解法并不完全正确,但结果却与设想并不一致

/*
struct RandomListNode {
    int label;
    struct RandomListNode *next, *random;
    RandomListNode(int x) :
            label(x), next(NULL), random(NULL) {
    }
};
*/
class Solution {
public:
    vector<RandomListNode> c;
    RandomListNode* Clone(RandomListNode* pHead)
    {
        RandomListNode np=*pHead;
        if(!pHead)
            return &np;
        
        while(pHead)
        {
            c.push_back(*pHead);
            pHead=pHead->next;
        }
        for(int i=0;i<c.size()-1;i++)
        {
            c[i].next=&c[i+1];
        }
        RandomListNode* pp=&c[0];
        return pp;
    }
};

结果输出:

不通过
您的代码已保存
答案错误:您提交的程序没有通过所有的测试用例
case通过率为0.00%
测试用例: {1,2,3,4,5,3,5,#,2,#}
对应输出应该为: {1,2,3,4,5,3,5,#,2,#}
你的输出为: 空。请检查一下你的代码,有没有循环输入处理多个case

此处应有输出,且输出不应为空,但由于牛客网本身的局限性,导致此处输出与设想不一致。
牛客网此题在大部分情况下只有通过两种结果。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值