目录
1.题目解析
题目连接:力扣
首先要理解题目的原意,才能正确理解这道题目的解法:
题目的大概意思就叫我们复制一份题目中的链表,并返回新链表的头
这题看似只是复制,但是这题目并不简单
新链表指针也应该指向新节点
那么next指针很容易做得到的,但是random是比较难,因为random指针不是单纯的指向下一个节点,而是没有顺序的
它可能指向自己,可以可能指向空,也可能两个指针同时指向一个节点
那么遍历去拷贝到新链表,明显是行不通的
那这题我们该怎么解题呢?
2.解题思路
解题总共需要三步
第一步:
我们在每个节点后面申请新的节点
并且新的节点是前一个节点的值的拷贝
总结来说 copy就是cur的一份拷贝,只不过cur的next和random指针没有拷贝过去
并且让他们连接起来
(他们其实就是一个链表,copy之所以在上面,我是想让读者知道他们是插入的新节点)
第二步:
接下来把新节点copy的random指针指向 cur的random指向的地方,就是把cur的random拷贝到copy里。
相当于copy就是cur的值和random的指针的一份拷贝
然后用循环去解决
这样是不是可以看出 我们就拷贝了cur (只不过cur的next不拷贝过去)
这样我们就拷贝了一遍原链表
第三部:
把已经拷贝好的节点,连接到一起
我们一样 创建新链表的头和尾,然后把这些节点依次拷贝到新链表里面。
最后我们返回新链表的头。
这道题我们就解决了
3.思路转换为代码
第一步:
要在链表的每个节点后面新创建一个节点,当然需要malloc来申请
这里可以有两种写法(效果都一样)
第一种:
我们创建两个指针,一个指向头,一个指向头的下一个节点
然后利用这两个节点,在这两个节点中插入一个新节点
然后让这两个指针同时向后移动,保持他们是一个在前,一个在后的状态
逻辑图如上
代码如下
struct Node* cur=head; while(cur)//分别在每个节点的后面创建一个新节点 { struct Node* copy=(struct Node*)malloc(sizeof(struct Node)); struct Node* end=cur->next; copy->next=end; cur->next=copy; copy->val=cur->val; cur=end; }
第二种:
我们只创建一个指针。
插入新节点时,需要注意顺序,一定要让新节点先指向后一个节点,在让前一个节点指向新节点,这里有点绕,我放图会跟清晰
如果你先执行2时 那么cur->next已经改变,指向了新节点,那么唯一能找到第二个节点的指针就被该了,那么copy就找不到下一个节点。
所以我跟推荐用第一种,第一种的顺序不必要这么准确
第二步:
因为刚才cur通过循环已经走到NULL了
1.这一次我们要让它从头开始遍历,所以我们要让cur重置为head
2.然后我要找到copy的位置,copy都是cur的拷贝,当然就是在cur->next
4.前面说了,cur->random可能为空,所以我们对这个情况要单独判断下
5.因为我们要让新节点连接 所以random一定要指向新节点 (cur->random->next)
6.最后让cur移动 移动到下一个的下一个节点(注意,要移动到旧节点。而不是新节点)
第三步:
接下来我们就要把新节点全部连接到新的链表里
1.先创建新链表的头和尾,cur要重新遍历,所以cur要重置为head
然后我们再创建两个指针
一个是指向copy(copy)一个是指向copy的下一个节点(end)
2.让cur重新指向旧节点,让他们还原,不在指向新节点
3.第一次进入时,头和尾为空,所以我们要单独处理这个情况
4.其余条件我们正常接入节点
5.让cur移动到end的位置(相当于移动)
6.最后我们返回新链表的头
4.源码
struct Node* copyRandomList(struct Node* head) {
struct Node* cur=head;
while(cur)//分别在每个节点的后面创建一个新节点
{
struct Node* copy=(struct Node*)malloc(sizeof(struct Node));
struct Node* end=cur->next;
copy->next=end;
cur->next=copy;
copy->val=cur->val;
cur=end;
}
cur=head;
while(cur)
{ //把copy(新节点)的random指向cur->random的后一个节点
struct Node* copy=cur->next;//这个后一个节点正是cur的值
if(cur->random==NULL)
{
copy->random=NULL;
}
else
{
copy->random=cur->random->next;
}
cur=cur->next->next;
}
struct Node* Headhead=NULL,*Tailhead=NULL;
cur=head;
while(cur)
{ //把copy全部链接到新的链表里
struct Node* copy=cur->next;
struct Node* end=copy->next;
cur->next=end;
if(Tailhead==NULL)
{
Tailhead=Headhead=copy;
}
else
{
Tailhead->next=copy;
Tailhead=Tailhead->next;
}
cur=end;
}
return Headhead;
}
如果本章对你有帮助,希望能获得你的赞~