当前位置: 首页 > news >正文

环形链表问题与随机链表的复制oj复盘

1.环形链表

1.1 环形链表1

https://leetcode.cn/problems/linked-list-cycle/

/** * Definition for singly-linked list. * struct ListNode { * int val; * struct ListNode *next; * }; */typedefstructListNodeListNode;boolhasCycle(structListNode*head){if(head==NULL||head->next==NULL){returnfalse;}ListNode*slow=head;ListNode*fast=head;while(fast&&fast->next){slow=slow->next;fast=fast->next->next;if(slow==fast){returntrue;}}returnfalse;}

解题思路:快慢指针

想象两个人在环形跑道上跑步:

  • 一个人跑得快(每次两步)

  • 一个人跑得慢(每次一步)

  • 如果跑道是环形的,那么快的人最终会追上慢的人(也就是相遇)。如果跑道是直的(无环),快的人会先跑到终点(NULL)。

在链表中,我们设置两个指针:

  • slow:每次走一步

  • fast:每次走两步

  • 从 head 出发,如果链表有环,则 fast 一定会追上 slow(它们相遇);如果无环,fast 会先遇到 NULL。

思路还是很简单的,就是简单的快慢指针,但是我们在这里来点更深层次的思考,这里有如下两个问题:

思考1:为什么快指针每次走两步,慢指针走一步可以相遇,有没有可能遇不上,请推理证明!
答案是肯定的,以下为证明:
由于fast与slow的相对速度差为1,假设我们设在slow进环时,slow与fast的距离为N,那么下一次由于速度差为1,所以下一次的距离为N-1,以此类推。下一次就是N-2,…,直到,3,2,1,0。
所以由此可见当相对速度差为1时,是一定可以相遇的,即当N等于0时就相遇了。

思考2:快指针一次走3步,走4步,…n步行吗?

我们来总结一下:
总结一下:

1、N是偶数,第一轮就追上了
2、N是奇数,第一轮追击会错过,距离变成C-1
a、如果C-1是偶数,下一轮就追上了
b、如果C-1是奇数,那么就永远追不上

那么我们再来思考一个问题,存不存在一种情况不可能追得上呢?
要想满足这个条件,是不是就是得保证N是奇数同时C-1是奇数,也就是说C是偶数的情况呢?
我们来试着证明看看:

综上所述:
不存在一定不可能追得上的情况。
只有奇数-奇数才能等于偶数
偶数一定是偶数
(x+1)∗偶数一定是偶数

所以反正N是奇数且C的偶数不能同时存在,永远追不上的条件不成立

结论:一定能追上

  • N偶数第一轮就追上了
  • N是奇数第一轮追不上,C-1是偶数第二轮就追上

1.2 环形链表2

https://leetcode.cn/problems/linked-list-cycle-ii/description/

/** * Definition for singly-linked list. * struct ListNode { * int val; * struct ListNode *next; * }; */typedefstructListNodeListNode;structListNode*detectCycle(structListNode*head){if(head==NULL||head->next==NULL){returnNULL;}ListNode*slow=head;ListNode*fast=head;while(fast&&fast->next){slow=slow->next;fast=fast->next->next;if(slow==fast){ListNode*meet=slow;while(head!=meet){meet=meet->next;head=head->next;}returnmeet;}}returnNULL;}
  • 当快慢指针相遇时,将 meet 指向相遇点(此时 slow 和 fast 都在相遇点)。

  • 然后让 head 指针从链表头开始,meet 指针从相遇点开始,两者同时每次移动一步。

  • 根据数学推导,当它们再次相遇时,相遇点即为环的入口。

  • 循环条件 head != meet 保证了只要两个指针不相等就继续移动。

  • 一旦相等,循环结束,返回此时的节点(即入口)。

为什么这样能找到入口?
设:

  • 头节点到环入口的距离为 a

  • 环入口到相遇点的距离为 b(顺时针方向)

  • 相遇点到环入口的距离为 c(即环剩余部分,环长 L = b + c)

  • 当快慢指针相遇时,慢指针走了 a + b 步,快指针走了 a + b + nL 步(n 为快指针在环内多走的圈数)。由于快指针速度是慢指针的两倍,有:

2(a+b)=a+b+nL=>a+b=nL=>a=nL-b=(n-1)L+c

这意味着从相遇点出发,走 c 步即可到达入口,而从 head 出发走 a 步也到达入口,且 a 正好等于 (n-1)L + c。因此,让两个指针分别从 head 和相遇点以相同速度移动,它们必然在入口处相遇。
也就是说其实就是在head向入口走时,meet一直在环内绕圈。

2.随机链表的复制

https://leetcode.cn/problems/copy-list-with-random-pointer/description/

/** * Definition for a Node. * struct Node { * int val; * struct Node *next; * struct Node *random; * }; */typedefstructNodeNode;structNode*copyRandomList(structNode*head){Node*curr=head;//拷贝while(curr){Node*copy=(Node*)malloc(sizeof(Node));copy->val=curr->val;copy->next=curr->next;curr->next=copy;curr=copy->next;}curr=head;while(curr){Node*copy=curr->next;if(curr->random==NULL){copy->random=NULL;}else{copy->random=curr->random->next;}curr=copy->next;}curr=head;Node*newHead=NULL;Node*Tail=NULL;while(curr){Node*copy=curr->next;Node*next=copy->next;if(Tail==NULL){newHead=Tail=copy;}else{Tail->next=copy;Tail=copy;}curr=next;}returnnewHead;}

代码整体结构:

  • 拷贝节点并插入原链表(在原节点后插入复制节点)

  • 设置复制节点的 random 指针

  • 分离原链表和复制链表(拆分成两个独立的链表)

这种做法的核心思想是:利用原节点的 next 指针建立原节点与复制节点的一一对应关系,从而方便地找到 random 指针应该指向的复制节点。
第一部分:拷贝节点并插入
思路

  • 遍历原链表,对每个原节点 curr,创建一个新节点 copy,值与原节点相同。

  • 将 copy 插入到 curr 和 curr->next 之间:

  • copy->next 指向 curr 原来的下一个节点。

  • curr->next 指向 copy。

  • 然后 curr 移动到 copy->next,即原链表的下一个节点,继续处理。

第二部分:设置复制节点的 random
思路

  • 再次遍历,每次处理一对节点:原节点 curr 和它的复制节点 copy(即 curr->next)。

  • 原节点的 random 可能指向某个节点 rand,那么复制节点的 random 就应该指向 rand 的复制节点,即 rand->next(因为每个原节点的复制节点都在它后面)。

  • 如果 curr->random 为 NULL,则复制节点的 random 也设为 NULL。

第三部分:分离两个链表
思路

  • 再次遍历交错链表,这次要把它拆分成两个独立链表:

  • 原链表:每个原节点的 next 应该指向它原来的下一个原节点(即 copy->next)。

  • 复制链表:每个复制节点的 next 应该指向下一个复制节点。

http://www.jsqmd.com/news/454045/

相关文章:

  • Matlab布谷鸟优化算法CS原代码集,包含基准测试函数,适用于后续改进与对比,百分百可运行
  • 广州前十留学机构实测!申请躺赢全靠它 - 博客湾
  • 【MySQL】复合查询
  • 探索Matlab/Simulink在电力调频中的多元应用:从传统到新能源的转变
  • 【MySQL】视图、用户和权限管理
  • VulnHub DC-7 靶机渗透测试笔记
  • GitHub 今日热搜:24小时内最受瞩目的10个开源项目
  • 2026年铝型材厂家推荐排行榜:工业铝型材、角铝型材、欧标铝型材、铝合金铝型材、铝型材框架定制、工作台与置物架方铝型材实力品牌精选 - 品牌企业推荐师(官方)
  • 基于遗传粒子群优化算法的LSTM网络预测优化:精准预测与超越局部最优解的挑战
  • 2026年全国薪酬绩效咨询公司哪家靠谱?口碑好实力强适配多行业 靠谱专业且落地性强 - 深度智识库
  • 东莞九头牛软件科技小龙虾openclaw,以创新技术开启AI民主化与GEO平权新时代
  • OpenClaw 配置 Nginx 反向代理完整指南
  • 永磁同步电机控制仿真之旅
  • 使用宝塔一键迁移插件来迁移项目
  • Rust 1.94.0 闪亮登台
  • 【MySQL系列文章】Linux环境下安装部署MySQL
  • 保险企业局域网如何用Java保障理赔材料文件夹的断点续传防篡改?
  • X光、CT、MRI、超声等影像识别如何是大模型AI诊断
  • ITS是什么
  • [特殊字符]家人们,今天来给大家分享一款超厉害的闭环步进驱动器源码![特殊字符]
  • Linux线程(3)线程控制
  • 探寻2026年安徽口碑好的AI搜索推广专业公司,价格怎么收费 - 工业推荐榜
  • 永磁同步电机无位置观测算法:实测有效的宝藏秘籍
  • 【RabbitMQ】超详细Windows系统下RabbitMQ的安装配置
  • 2026年深圳配眼镜品牌全、服务好的配镜中心排名大揭秘 - mypinpai
  • 2026年工业移动电源厂家推荐排行榜:大功率/220V/380V/便携式/应急/工程施工/大容量/快充/消防救援/户外/储能式移动电源,专业实力与创新技术深度解析 - 品牌企业推荐师(官方)
  • 计算机毕设java的高校车辆租赁管理系统 基于SpringBoot框架的校园汽车共享与调度服务平台 Java技术驱动的高校公务车辆与共享出行一体化管理系统
  • Simulink车用永磁同步电机弱磁控制的矢量控制FOC
  • 2026年腾讯企业邮箱开通服务商怎么选:资质、价格与服务对比详解 - 品牌2026
  • 镀锌板水箱选购指南:核心要素解析+Top5厂家推荐,工业与市政项目必看 - 深度智识库