
示例 1:

输入:head = [[7,null],[13,0],[11,4],[10,2],[1,0]]
输出:[[7,null],[13,0],[11,4],[10,2],[1,0]]
示例 2:

输入:head = [[1,1],[2,1]]
输出:[[1,1],[2,1]]
示例 3:

输入:head = [[3,null],[3,0],[3,null]]
输出:[[3,null],[3,0],[3,null]]
提示:
此题是力扣上一道中等难度的题目,不过相信很多同学在看了这道题目之后都点云里雾里的感觉,觉得这道题很复杂的样子,一个链表有两个指针域,而且有一个还是随机指针,对于题目的描述完全不读懂它在讲点什么。
是的,这道题虽说是中等难度的题目,但是在我看来本题算是链表章节的题目中比较综合的题,虽然它没有【环形链表】那么绕,需要一些数学的思维,但它的结构是比较复杂的,需要做题者对于链表的掌握程度达到一定的水准,不然得话在处理其指针的关系时就会思绪混乱、无从下手
先行说明,这种思路的时间复杂度是O(3N),最后进行大O渐进法的优化就是O(N)
Node* cur = head;
while(cur)
{
Node* copy = (Node *)malloc(sizeof(Node));
copy->val = cur->val;
//插入结点
Node* nextNode = cur->next;
cur->next = copy;
copy->next = nextNode;
//迭代
cur = nextNode;
}
我们继续看下去。一样,这个【11】可以通过源节点【11】的【random】域所指向的【1】,然后去找到它后面的一个结点,然后【copy->next】等于它即可
cur = head;
while(cur)
{
Node* copy = cur->next;
if(cur->random == NULL)
copy->random = NULL;
else
//拷贝结点的随机指针即为原结点的随机指针所指向结点的下一个结点
copy->random = cur->random->next;
//迭代(移动两步)
cur = copy->next;
}
好,插了一个题外话,我们继续分析这第三个步骤
展示一下整体的代码,不过还是自己去敲一遍比较好哦
/*
// Definition for a Node.
class Node {
public:
int val;
Node* next;
Node* random;
Node(int _val) {
val = _val;
next = NULL;
random = NULL;
}
};
*/
class Solution {
public:
Node* copyRandomList(Node* head) {
//1、把复制的结点插入到原结点后
Node* cur = head;
while(cur)
{
Node* copy = (Node *)malloc(sizeof(Node));
copy->val = cur->val;
//插入结点
Node* nextNode = cur->next;
cur->next = copy;
copy->next = nextNode;
//迭代
cur = nextNode;
}
//2、设置拷贝结点的random值
cur = head;
while(cur)
{
Node* copy = cur->next;
if(cur->random == NULL)
copy->random = NULL;
else
//拷贝结点的随机指针即为原结点的随机指针所指向结点的下一个结点
copy->random = cur->random->next;
//迭代(移动两步)
cur = copy->next;
}
//3、提取复制后的链表恢复原链表
cur = head;
Node* copyHead, *copyTail;
copyHead = copyTail = NULL;
while(cur)
{
Node* copy = cur->next;
Node* nextNode = copy->next;
//恢复原链表的指向
cur->next = nextNode;
//尾插逻辑
if(copyTail == NULL)
{
copyHead = copyTail = copy;
}
else
{
copyTail->next = copy;
copyTail = copyTail->next;
}
cur = nextNode;
}
return copyHead;
}
};
以上就是本文所要描述的所有内容,感谢您对本文的观看,如有疑问请于评论区留言或者私信我都可以🍀