复制带随机指针的链表

给定一个带有额外随机指针的链表,该指针可能指向链表中的任何节点或空节点,任务是实现链表的深拷贝。题目提供了一个示例及操作步骤,包括拷贝节点、设置随机指针和拆分原链表。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

题目:

给定一个链表,每个节点包含一个额外增加的随机指针,该指针可以指向链表中的任何节点或空节点。

要求返回这个链表的深拷贝。

示例:

输入:
{"$id":"1","next":{"$id":"2","next":null,"random":{"$ref":"2"},"val":2},"random":{"$ref":"2"},"val":1}

解释:
节点 1 的值是 1,它的下一个指针和随机指针都指向节点 2 。
节点 2 的值是 2,它的下一个指针指向 null,随机指针指向它自己。

提示:

你必须返回给定头的拷贝作为对克隆列表的引用。

分析:

分三步走:(1)拷贝原链表节点(2)置每个节点的random指针(注意不空和空的时候都要进行置)(3)拆分原链表

 //RandomListNode* Clone(RandomListNode* pHead)
    Node* copyRandomList(Node* head)
    { 
        if(head==nullptr) 
            return nullptr; 
        //第一步:复制链表结点 
        Node* oldnode=head; 
        while(oldnode) 
        { 
            Node* newnode = new Node(oldnode->val);
            //用老节点的值申请一个新节点 
            newnode->next=oldnode->next;
            //将新节点的next链上老节点的next 
            oldnode->next=newnode;
            //将新节点插在老节点后面
            if(oldnode->next)
                oldnode=oldnode->next->next;
            //由于已经插入了新节点,因此遍历下一个老节点得走2个next 
        } 
        
        //第二步:置信结点的random指针klll'``
        oldnode=head;
        //oldnode指向链表的开始 
        while(oldnode) 
        { 
            Node* newnode=oldnode->next;
            //由于上面的复制,新节点紧跟在与其对应的老节点后面 
            if(oldnode->random!=nullptr) 
            { 
                //oldnode->random是老节点的random域,再指向next就是该老节点对应的新节点应该指向的对应的random域 
                newnode->random=oldnode->random->next; 
            }
            else//当老节点的random指针域为空时,也要将新节点的random指针域置空
            {
                newnode->random=nullptr;
            }
            
            oldnode=oldnode->next->next;
            //只走老节点(为其对应的新节点链上对应的randoum域) 
        } 
        
        //拆分新/老链表 
        oldnode=head;
        //让oldnode指向链表开始 
        Node* newHead=oldnode->next;
        //新链表的头是老链表头的下一个(之前复制了的) 
        while(oldnode) 
        { 
            Node* newnode=oldnode->next;
            //保证newnode一直紧跟咋oldnode后面(老、新节点相对位置) 
            
            if(newnode != nullptr)
                oldnode->next=newnode->next;//恢复老节点的next指向 
            if(oldnode->next!=nullptr) 
            { 
                newnode->next=oldnode->next->next;
                //恢复新节点的next指向 
            } 
            oldnode=oldnode->next;//由于oldnode的next域上面已经恢复了,因此下一个老节点就是oldnode->next 
        } 
        return newHead; 
    }
    
    
    
    
    /*Node* copyRandomList(Node* head) 
    {
        if(head==nullptr)
            return nullptr;
        
        //复制
        Node* old=head;
        while(old)
        {
            Node* newnode=new Node(old->val);//利用旧节点创建新节点
            newnode->next=old->next;
            old->next=newnode;
            old=old->next->next;//插入一个新的,但是每次都只走旧节点
        }
        
        //置randow指针
        old=head;
        while(old)
        {
            Node* newnode=old->next;//新节点
            if(old->random)
            {
                newnode->random=old->random->next;
            }
            else
            {
                newnode->random=nullptr;
            }
            old=old->next->next;//只走旧节点
        }
        
        //拆分
        old=head;//旧头
        Node* newHead=old->next;//新头
        while(old)
        {
            Node* newnode=old->next;//一直在old后面,即被复制的节点
            //old=next->next;//回复旧节点指向
            old->next=newnode->next;
            if(old->next)
                newnode->next=old->next->next;//回复老的节点指向
            old=old->next;//由于上一个新老节点均恢复指向,因此只需原来的而节点移动
        }
        return newHead;
    }*/
    

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值