题目描述
题目链接:138. 随机链表的复制 - 力扣(LeetCode)
题目分析
这个题目很长,但是意思其实很简单:就是一个单链表,每个结点多了一个指针random随机指向链表中的任意结点或者NULL,我们血需要复制这个链表,连同random一起复制下来
思路一
思路一是我们用cur遍历链表,用for循环找random对应的原链表中的random,这个算法找每个random的时间复杂度都是O(N),整个算法的时间复杂度是O(N^2)
思路二
思路二是分三步走:
- 将copy结点链接到原结点的next
- copy结点的random指向对应原结点random的next
- 把copy链表拆接下来尾插到新链表
这个思路更优,时间复杂度是O(N)
画图
我们可以简单画图来演示一下这三步:
1.copy结点插入到原结点的next
定义cur遍历链表,用malloc开辟一个copy的空间,然后依次将cur->val赋给copy->val,接着将copy结点插入到cur和cur->next之间,cur走到copy-.>next
2.处理copy结点的random
让cur回到head,经过第一步之后我们知道copy就是cur->next,这里我们分为两种情况:
- 如果cur->random指向NULL,则copy->next也指向NULL
- 否则copy->random指向cur->random->next
然后cur走到cur->next->next
3.copy结点拆解下来进行尾插
最后一步就是尾插,定义newhead和tail先指向NULL,cur回到head,copy是cur->next,next保存copy->next
将cpoy尾插到tail,将cur->next接到next恢复原链表,最后返回newhead
代码示例
我们根据思路二来写代码:
/**
* Definition for a Node.
* struct Node {
* int val;
* struct Node *next;
* struct Node *random;
* };
*/
struct Node* copyRandomList(struct Node* head) {
//copy结点插入到原结点的后面
struct Node*cur=head;
while(cur)
{
struct Node*copy=(struct Node*)malloc(sizeof(struct Node));
copy->val=cur->val;
copy->next=cur->next;
cur->next=copy;
cur=cur->next->next;
}
//处理copy结点的random
cur=head;
while(cur)
{
struct Node*copy=cur->next;
if(cur->random==NULL)
{
copy->random=NULL;
}
else
{
copy->random=cur->random->next;
}
cur=cur->next->next;
}
//copy结点拆下来尾插
cur=head;
struct Node*newhead=NULL,*tail=NULL;
while(cur)
{
struct Node*copy=cur->next;
struct Node*next=copy->next;
if(tail==NULL)
{
newhead=tail=copy;
}
else
{
tail->next=copy;
tail=tail->next;
}
cur->next=next;
cur=next;
}
return newhead;
}
结果同样通过: