题目描述
题目链接: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结点的randomcur=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;
}
结果同样通过: