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

完整教程:数据结构:单链表的应用(力扣算法题)第二章

完整教程:数据结构:单链表的应用(力扣算法题)第二章

每题代码汇总:登录 - Gitee.com

上一章回顾:数据结构:单链表的应用(力扣算法题)第一章-CSDN博客

1.相交链表

160. 相交链表 - 力扣(LeetCode)

理解题意:

思路:

分别遍历两条单链表的长度,两条单链表长度相减,得到长度差的绝对值,让长一些的链表往前遍历长度差个结点,再让两条链表同步遍历,找相同结点。

注意:此处相同是指地址相同而不是值相同。

代码见下:

typedef struct ListNode ListNode;
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
//求链表长度
ListNode* pa = headA;
ListNode* pb = headB;
int sizeA = 0, sizeB = 0;
while(pa)
{
++sizeA;
pa = pa->next;
}
while(pb)
{
++sizeB;
pb = pb->next;
}
//求链表长度差
int gap = abs(sizeA - sizeB);//得到的是绝对值
//定义长短链表
//假设
ListNode* shortlist = headA;
ListNode* longlist = headB;
if(sizeA > sizeB)
{
longlist = headA;
shortlist = headB;
}
//长链表往前遍历
while(gap--)
{
longlist = longlist->next;
}
//两链表一起走
while(shortlist && longlist)
{
if(shortlist == longlist)
{
return shortlist;
}
shortlist = shortlist->next;
longlist = longlist->next;
}
//不相交
return NULL;
}

最终通过测试。

注意:

2.环形链表

141. 环形链表 - 力扣(LeetCode)

理解题意:

思路一:

使用快慢指针,慢指针一次走一步,快指针一次走两步,如果快指针和慢指针指向同一个结点,说明链表带环。

代码见下:

typedef struct ListNode ListNode;
bool hasCycle(struct ListNode *head) {
ListNode* slow = head;
ListNode* fast = head;
while(fast && fast->next)
{
slow = slow->next;
fast = fast->next->next;
if(slow == fast)
{
return true;
}
}
return false;
}

最终通过测试。

证明一:

证明为什么快指针每次走两步,慢指针每次走一步就可以相遇?

当slow刚入环时,其与fast的距离最远,假设为N,那么当slow走一步,fast走两步时,距离变为N-1,以此类推,最终N == 0。

证明二:

当快指针每次走3步,走4步……还能满足条件吗?

以每次走三步为例,并且需要对N进行分类讨论:

此时可以得到永远不能相遇的条件:N为奇数,C为偶数。那么,此条件正确吗?

此处假设环的周长为C,头结点到slow结点的长度为L。并且此时fast指针已经环绕X周。

依旧沿用上面的条件:3 * 慢指针路程 == 快指针路程

在追逐过程中,快慢指针所走过的路径长度:

fast:L + xC + C - N

slow:L

此时建立方程式:3L == L + xC + C - N

得:2L == (x+1)C - N,此时分两种情况:

情况1:偶数 = 偶数 - 偶数

情况2:偶数 = 奇数 - 奇数

此时可以证明上述得到的结论:N为奇数,C为偶数 不成立,则当快指针每次走3步,走4步……时,两指针依旧会相遇。

思路二:

使用快慢指针,快指针走3,4,5……步

代码如下:

typedef struct ListNode ListNode;
bool hasCycle(struct ListNode* head) {
ListNode *slow, *fast;
slow = fast = head;
while (fast && fast->next) {
slow = slow->next;
int n = 4; // fast每次⾛三,四……步
while (n--) {
if (fast->next)
fast = fast->next;
else
return false;
}
if (slow == fast) {
return true;
}
}
return false;
}

最终测试通过。

总结:虽然已经证明了快指针不论走多少步都可以满足在带环链表中相遇,但是在编写代码的时候 会有额外的步骤引入,涉及到快慢指针的算法题中通常习惯使用慢指针走⼀步快指针走两步的方式。

3.环形链表II

142. 环形链表 II - 力扣(LeetCode)

理解题意:

思路:

使用快慢指针,在环里一定会有相遇点,此时:相遇点到入环结点的距离 == 头结点到入环结点的距离。

代码如下:

typedef struct ListNode ListNode;
struct ListNode *detectCycle(struct ListNode *head) {
//创建快慢指针
ListNode* slow = head;
ListNode* fast = head;
while(fast && fast->next)
{
slow = slow->next;
fast = fast->next->next;
if(slow == fast)
{
//相遇点:使用curr == slow,不动head,且使curr与slow一样每次走一步
ListNode* curr = head;
while(curr != slow)
{
curr = curr->next;
slow = slow->next;
}
//入环第一个结点
return curr;
}
}
//不带环
return NULL;
}

最终测试通过。

证明:

为什么在带环链表中,快慢指针相遇点到入环结点的距离 == 头结点到入环结点的距离?

此处,E为入环结点,M为相遇点,R为周长,L为头结点到入环结点的距离。

快慢指针在相遇点走的总路程:

slow = L + X

fast = L + X + nR,nR为fast指针的路程。

因为:2 * slow = fast

则:L = nR - X

L = (n - 1)R + R - X   ,其中,L为头结点到入环结点的距离,R-X为相遇点到入环结点的距离。此时,(n-1)R可省略,不影响结果。

本章完。

http://www.hskmm.com/?act=detail&tid=9989

相关文章:

  • CF2039E Shohag Loves Inversions
  • U522155 板垣 カノエ is WATCHING YOU std
  • ctfshow web
  • 代码随想录算法训练营第三天 | leetcode 203 707 206
  • Codeforces Round 1051 (Div. 2) A~D2
  • 【F#学习】数组:Array
  • CTFWEB姿势总结
  • 规模化加速AI:从用户、开发者到企业的深度策略解析
  • ctfshow 菜狗杯
  • 国际服务器(VPS):泰国、印尼、菲律宾、马来西亚、香港、台湾、新加坡、日本、美国、英国等。
  • 缓存常见问题
  • ctfshow 电子取证
  • Hello,World!
  • 最新IDEA 2025 专业版破解永久破解教程(附资源)intellij IDEA
  • AtCoder ABC423F - Loud Cicada 题解 容斥原理
  • 1756:八皇后
  • 矩阵置零-leetcode
  • 嘉立创常用快捷键
  • 02020402 EF Core基础02-EF Core数据的增删改查
  • conda 无法安装依赖 CondaHTTPError: HTTP 000 CONNECTION FAILED for url: tsinghua tencentaliyun
  • 牛客刷题-Day2
  • 图解支付系统账务系统核心设计 - 智慧园区
  • vulnhub(持续更新)
  • 小爱同学连接电脑进行交互 教程
  • 网络流初步浅谈:EK与Dinic
  • 解码C语言结构体
  • 已完成今日求所有满足长为 $a$ 的和为 $b$ 的按位或为 $c$ 的非负整数序列的异或和的异或和大学习
  • Hello Yqc!
  • 2025.9.19——卷9-10选择
  • 软件工程学习日志2025.9.19