leetcode 138. Copy List with Random Pointer

本文探讨了一种特殊的链表结构,该链表除了常规的next指针外还包含一个随机指针。文章详细介绍了三种不同的深拷贝实现方法:暴力法、使用哈希表的解决方案及一种空间复杂度为O(1)的方法。

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

Description:
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.

加上了一个随机指针的链表,随机指针会随机地指向链表中的任意一个节点或者NULL,要求实现深拷贝。

Solution:
一开始理解错题意了,以为random指针还是直接指向原来的地址即可,后面细细一想,发现并没有那么简单。
这题也出现在《剑指offer》这本书上,看了解法之后越来越觉得这是一个好题,经典题,此题有三种解法,从坏到好一一细说:
Ⅰ超级暴力法。
1、其实难点就是在于我们不知道random指针指向的是哪个节点,既然不知道,那么我们就逐一遍历找到它指向的是第几个节点;
2、在深拷贝时,我们先实现好基本不包括random指针的链表;
3、之后在对原链表进行遍历找出每个的random指针指向的是第几个节点,然后找到新链表对应的下标节点,即可。
时间复杂度为O(n²),空间复杂度为O(1)

Ⅱ map实现(哈希表)
1、我们其实不需要random指向的是第几个节点,我们只需要建立好一个新节点与旧节点的一一对应关系即可;
2、建立好了之后,我们通过random指向的旧节点和map对应关系就能知道新节点的地方。
时间复杂度为O(n),空间复杂度为O(n)

Ⅲ O(1)空间复杂度实现
假如原链表表示为A(C)->B(A)->C(A)->NULL,括号里表示为随机指向的节点;
1、我们先将链表拷贝成如此:
A(C)->A’->B(A)->B’->C(A)->C’->NULL
即将旧链表的每一个节点的next指针指向新链表对应节点,换句话说,就是将新链表间隔地插入旧链表中。

2、拷贝random指针,执行了第一步之后,我们需要找random指针就好找许多,如下:

oldnode->next->random=oldnode->random->next

完成拷贝之后链表如下:
A(C)->A’(C’)->B(A)->B’(A’)->C(A)->C’(A’)->NULL

3、将新链表和旧链表分离即可,得到两个链表:
A(C)->B(A)->C(A)->NULL
A’(C’)->B’(A’)->C’(A’)->NULL

如此做的做法时间复杂度为O(n),空间复杂度为O(1)

Code:
Ⅱ:

class Solution {
public:
    RandomListNode *copyRandomList(RandomListNode *head) {
        map<RandomListNode*, RandomListNode*> newold;
        RandomListNode* oldtemp = head;
        if (head == NULL)
            return head;
        RandomListNode* pre = NULL;
        RandomListNode* newhead = NULL;
        while (head)
        {
            RandomListNode* cur = new RandomListNode(head->label);
            newold[head] = cur;//build a relationship between new nodes and old nodes
            if (pre)
                pre->next = cur;
            else
                newhead = cur;
            pre = cur;
            head = head->next;
        }
        while (oldtemp)
        {
            newold[oldtemp]->random=newold[oldtemp->random];
            oldtemp=oldtemp->next;
        }
        return newhead;
    }
};

Ⅲ:

class Solution {
public:
    RandomListNode *copyRandomList(RandomListNode *head) {
        RandomListNode* temp=head;
        if(!head)
            return head;
        while(temp)
        {
            RandomListNode* align=new RandomListNode(temp->label);
            align->next=temp->next;
            temp->next=align;
            temp=align->next;
        }//the first step
        temp=head;
        while(temp)
        {
            if(temp->random)
                temp->next->random=temp->random->next;
            temp=temp->next->next;
        }//the second step
        temp=head;
        RandomListNode* ans=temp->next;
        while(temp)
        {
            RandomListNode* al=temp->next;
            temp->next=al->next;
            temp=al->next;
            if(al->next)
                al->next=al->next->next;
        }//split new link and old link
        return ans;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值