欢迎来到 s a y − f a l l 的文章 欢迎来到say-fall的文章 欢迎来到say−fall的文章

🌈这里是say-fall分享,感兴趣欢迎三连与评论区留言 🔥专栏: 《C语言从零开始到精通》 《C语言编程实战》 《数据结构与算法》 《小游戏与项目》 💪格言:做好你自己,你才能吸引更多人,并与他们共赢,这才是你最好的成长方式。
文章目录
题目:随机链表的复制
一、思路解析
该代码采用 "原地复制+拆分" 策略,高效实现复杂链表(每个节点含val、next指针、random指针)的深拷贝,核心优势是 时间复杂度O(n)、空间复杂度O(1)(不考虑目标链表存储空间),具体分3步:
1. 第一步:原地插入拷贝节点(构建"原节点-拷贝节点"成对结构)
- 遍历原链表的每个节点
pcur,为其创建一个拷贝节点NewNode(值与原节点相同,random初始为NULL)。 - 将拷贝节点插入到原节点的后面 (即
NewNode->next = pcur->next,再pcur->next = NewNode)。 - 最终原链表结构变为:
原节点1 -> 拷贝节点1 -> 原节点2 -> 拷贝节点2 -> ... -> 原节点n -> 拷贝节点n -> NULL。
2. 第二步:设置拷贝节点的random指针
- 再次遍历原链表(仅遍历原节点,步长为2:
pcur = pcur->next->next)。 - 对于每个原节点
pcur,其拷贝节点是pcur->next:- 若原节点
pcur的random为NULL,则拷贝节点的random也为NULL; - 若原节点
pcur的random指向原链表中的某节点A,则拷贝节点的random应指向A的拷贝节点(即A->next),这是该方法的核心巧思(利用第一步构建的成对结构,直接通过原节点的random找到拷贝节点)。
- 若原节点
3. 第三步:拆分原链表与拷贝链表
- 原链表的第一个拷贝节点(
head->next)即为新链表的头节点Newhead。 - 遍历拷贝链表(步长为2:
pcur = pcur->next->next),将拷贝节点的next指针指向下一个拷贝节点(跳过原节点),最终拆分出独立的拷贝链表。 - 原链表结构在拆分后会恢复(可选,该代码未显式恢复,但不影响拷贝结果)。
二、流程图
是 否 是 否 是 是 否 否 是 否 开始 原链表head是否为NULL? 返回NULL 结束 初始化pcur = head pcur ≠ NULL? 调用BuyNode创建拷贝节点
(val=pcur->val,next=pcur->next) prev = pcur,pcur = pcur->next prev->next = 拷贝节点
(插入原节点后) 重置pcur = head 【步骤1完成:原-拷成对结构】 pcur ≠ NULL 且 pcur->next ≠ NULL? pcopy = pcur->next(获取拷贝节点) pcur->random 是否为NULL? pcopy->random = NULL pcopy->random = pcur->random->next
(指向原random的拷贝节点) pcur = pcur->next->next(跳过拷贝节点) 【步骤2完成:random指针设置完毕】 Newhead = head->next(拷贝链表头)
pcur = Newhead pcur ≠ NULL 且 pcur->next ≠ NULL? pcur->next = pcur->next->next
(跳过原节点,连接下一个拷贝节点) pcur = pcur->next(移动到下一个拷贝节点) 【步骤3完成:链表拆分完毕】 返回Newhead
三、关键
- BuyNode函数作用 :封装拷贝节点的创建逻辑,确保拷贝节点的
next初始指向原节点的下一个节点,random初始为NULL。 - random指针设置的核心 :利用"原节点后紧跟拷贝节点"的结构,原节点
A的random指向B,则拷贝节点A'的random必然指向B'(B->next)。 - 拆分逻辑 :拷贝链表的节点在原链表中是"隔一个"存在的,因此只需将每个拷贝节点的
next指向其下一个拷贝节点(pcur->next->next)即可拆分出独立的拷贝链表。
四、代码
c
typedef struct Node Node;
Node* BuyNode(int x,Node* pcur)
{
Node* NewNode = (Node*)malloc(sizeof(Node));
NewNode->val = x;
NewNode->next = pcur->next;
NewNode->random = NULL;
return NewNode;
}
struct Node* copyRandomList(struct Node* head)
{
if(head == NULL)
{
return NULL;
}
Node* pcur = head;
while(pcur)
{
Node* NewNode = BuyNode(pcur->val,pcur);
Node* prev = pcur;
pcur = pcur->next;
prev->next = NewNode;
}
pcur = head;
while(pcur != NULL && pcur->next != NULL)
{
Node* pcopy = pcur->next;
if(pcur->random == NULL)
{
pcopy->random = NULL;
}
else
{
pcopy->random = pcur->random->next;
}
pcur = pcur->next->next;
}
Node* Newhead = head->next;
pcur = Newhead;
while(pcur!= NULL && pcur->next != NULL)
{
pcur->next = pcur->next->next;
pcur = pcur->next;
}
return Newhead;
}
- 本节完...
