目录
一、问题描述
oj链接:剑指 Offer 35. 复杂链表的复制 - 力扣(LeetCode)
二、思路一
2.1 分析
思路一的解法相对繁琐,一般我们使用思路二,具体步骤如下:
- 创建一个新链表,新链表每个节点的val值以及next的值都与原链表保持一致,random值暂且不管。
- 创建两个数组,一个数组num1存储原链表中每个结点的地址,另一个数组num2存储新链表中每个结点的地址。
- 原链表中结点的random对应于数组num1某个下标中的地址,记录下标,新链表的对应结点的random值即为数组num2中相同下标的地址。
具体图解如下:
2.2 代码
class Solution {
public:
Node* copyRandomList(Node* head) {
if(head==NULL)
{
return NULL;
}
Node* cur = head;
Node* newhead = NULL,*newtail = NULL;
int count = 0;
while(cur)
{
count++;
Node* newnode = (Node*)malloc(sizeof(Node));
if(newnode == NULL)
{
perror("malloc fail");
exit(-1);
}
newnode->val = cur->val;
newnode->next = NULL;
if(newhead == NULL)
{
newhead = newtail = newnode;
}
else
{
newtail->next = newnode;
newtail = newtail->next;
}
cur = cur->next;
}
Node* num1[count];
Node* num2[count];
int i = 0;
newtail = newhead;
cur = head;
while(cur)
{
num1[i] = cur;
i++;
cur = cur->next;
}
i = 0;
while(newtail)
{
num2[i] = newtail;
i++;
newtail = newtail->next;
}
cur = head;
newtail = newhead;
int x = 0;
while(cur)
{
if(cur->random==NULL)
{
newtail->random = NULL;
}
else
{
for(x = 0;x<i;x++)
{
if(cur->random == num1[x])
{
newtail->random = num2[x];
break;
}
}
}
cur = cur->next;
newtail = newtail->next;
}
return newhead;
}
};
三、思路二
3.1 分析
我们会发现在上述思路中最大的问题在于原链表中的结点与新链表的结点之间没有联系,所以我们就想到了一个办法,把新的拷贝节点连接到原链表的结点的后面。
具体步骤如下:
- 拷贝节点链接在原结点的后面。
- 拷贝节点的random等于原结点的random->next。
- 拷贝节点解下来,链接成一个新链表,恢复原链表。
3.2 代码
class Solution {
public:
Node* copyRandomList(Node* head) {
//1.插入拷贝节点到原结点的后面
Node* cur = head;
Node* copy = NULL;
while(cur)
{
//插入
copy = (Node*)malloc(sizeof(Node));
if(copy==NULL)
{
perror("malloc fail");
exit(-1);
}
copy->val = cur->val;
copy->next =NULL;
Node* next = cur->next;
copy->next = next;
cur->next = copy;
cur = next;
}
//处理拷贝的结点的random
cur = head;
while(cur)
{
copy = cur->next;
if(cur->random==NULL)
{
copy->random = NULL;
}
else
{
copy->random = cur->random->next;
}
cur = copy->next;
}
//拷贝节点解下来,链接成新链表,并且恢复原链表
cur = head;
Node* newhead = NULL,*newtail = NULL,*next = NULL;
while(cur)
{
copy = cur->next;
next = copy->next;
if(newhead == NULL)
{
newhead = newtail = copy;
}
else
{
newtail->next = copy;
newtail = newtail->next;
}
//恢复原链表
cur->next = next;
cur = next;
}
return newhead;
}
};