leetcode之Copy List with Random Pointer

本文详细介绍了链表复制算法的两种实现方式,包括保存映射关系的算法和不保存映射关系的算法,同时提供了相应的代码实现。

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

题目大意:

A linked list is given such that each node contains an additional random pointer which could point to any node in the list or null.

Return a deep copy of the list.

意思就是:

给定一个链表,该链表的每一的node包含next和random两个指针.请对该链表进行复制.

解题思路:

设原始链表如下,细线表示next指针,粗线表示random指针,没有画出的指针均指向NULL:

算法1:我们在构建新链表的节点时,保存原始链表的next指针映射关系,并把指针做如下变化(蓝色为原始链表节点,紫红色为新链表节点):

然后在上图的基础上进行如下两步

1、构建新链表的random指针:比如new1->random = new1->random->random->next, new2->random = NULL, new3-random = NULL, new4->random = new4->random->random->next

2、恢复原始链表:根据最开始保存的原始链表next指针映射关系恢复原始链表

该算法时间空间复杂度均为O(N)


算法2:该算法更为巧妙,不用保存原始链表的映射关系,构建新节点时,指针做如下变化,即把新节点插入到相应的旧节点后面:

同理分两步

1、构建新节点random指针:new1->random = old1->random->next, new2-random = NULL, new3-random = NULL, new4->random = old4->random->next

2、恢复原始链表以及构建新链表:例如old1->next = old1->next->next,  new1->next = new1->next->next

注意的两点是:

1,算法.

2,如何保存原来链表的对应关系,并在最后回复原来的链表.

 代码如下:

struct RandomListNode{
    int label;
    RandomListNode *next, *random;
    RandomListNode(int x) : label(x), next(NULL), random(NULL){}
};
class Solution{
    public:
        RandomListNode* copyRandomList(RandomListNode* head){
            if(!head){
                return NULL;
            }
            map<RandomListNode*, RandomListNode*> storage;
            storage[head] = head->next;
            RandomListNode* newHead = new RandomListNode(head->label);
            newHead->random = head;
            RandomListNode* current = head->next;
            head->next = newHead;
            RandomListNode* newCurrent = newHead;
            RandomListNode* oldCurrent = current;
            while(current){
                newCurrent->next = new RandomListNode(current->label);
                newCurrent->next->random = current;
                newCurrent = newCurrent->next;
                storage[current] = current->next;
                current = current->next;
                oldCurrent->next = newCurrent;    
                oldCurrent = current;    
            }
            newCurrent = newHead;
            while(newCurrent){
                if(!newCurrent->random->random){
                    newCurrent->random = NULL;
                }
                else{
                    newCurrent->random = newCurrent->random->random->next;
                }
                newCurrent = newCurrent->next;
            }
            current = head;
            for(int i=1;i<storage.size();i++){
                current->next = storage[current];
                current = current->next;
            }
            current->next = NULL;
            return newHead;
        }
};


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值