关于链表带环问题为什么要用快慢指针

2024-05-05 22:52

本文主要是介绍关于链表带环问题为什么要用快慢指针,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

判断链表是否带环

题目描述

给你一个链表的头节点 head ,判断链表中是否有环。

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos 不作为参数进行传递 。仅仅是为了标识链表的实际情况。

如果链表中存在环 ,则返回 true 。 否则,返回 false 。
在这里插入图片描述
这道题我们一般想到的就是用快慢指针来解决这道题首先设置两个指针fast和slow都从头开始,fast指针一次走两步,slow指针一次走一步,当这两个指针重回在一起的时候就是带环链表,如果没有重回就是不带环链表,代码也是非常简单的,下面是代码

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     struct ListNode *next;* };*/typedef struct ListNode listnode;
bool hasCycle(struct ListNode *head) {
listnode* fast = head;
listnode* slow = head;
if(head == NULL)
{return false;
}
while(fast && fast->next)
{fast = fast->next->next;slow = slow->next;if(slow == fast){return true;}}return false;
}

为什么要用快慢指针

我们可以先画一个图来看看,我们先创建一个带环链表
在这里插入图片描述
下面是指针走的过程
在这里插入图片描述
在这里插入图片描述
可以发现最终两个指针相遇了,并且当slow指针进环之后,fast与slow的距离每次在缩小一位,假设他们的距离是X,每走一步就是x-1,x-2最后一直到2,1,0所以他们两个会相遇,那么我们想个问题,如果快指针每次走3步,或者走4步呢,他们两个会不会相遇?
我们就拿走3步来说说,链表的长度为y我们假设长度为11,假设快指针和慢指针之间的距离长度为X,我们假设一个是7 ,快指针每次走3步,他们之间的距离就减去3,变成4,4在减去3,变成1,然后又减3变成-2,变成负数之后就相当于开始新一轮的追击了两个指针之间的距离就是,链表长度y-2就是9,9一直减去3就变成0,他们两个指针还是追上了。
如果他们两个之间的距离是8呢,画图来看看。
在这里插入图片描述
可以发现他们两个还是追上了
通过上面的分析,我们可以总结一下X是偶数,快指针每次走三步,他们两个的距离就缩小2,变成x-2,x-4,…4,2,0就追上了,如果x是奇数那么,x-2,x-4…3,1,-1当到-1时他们又开始新一轮的追击然后他们之间的距离就变成链表长度-1变成10,是偶数,最终偶数-2就会变成0,他们两个追上了。
这里我们得到两个结论
如果
1.两个指针之间的距离x是偶数那么第一轮就追的上
2.如果两个指针之间的距离是奇数第一轮追击追不上,变成链表长度-1,进入下一轮追击,如果是偶数就追上了,如果是奇数就追不上
如果是奇数,奇数减去偶数就永远不可能等于0
如果要永远追不上,那么就必须满足下面的条件
1.两指针之间的距离是奇数
2.链表长度是偶数

这两个条件会存在吗,画图来看看
我们可以试着推导一个公式出来看看
在这里插入图片描述
当入环的时候
slow走的距离是L
fast走的距离是L+XC+(C-N),(XC代表fast走的链表的环数,有可能这个链表环很小)
fast走的距离是slow的三倍
3L = L+XC+(C-N);
化简之后就变成2L = XC+C-N
提取公因式变成
2L = C(X+1)-N;
2L肯定是偶数,因为2是偶数偶数乘偶数一定是偶数。
如果要满足这个等式那么右边的等式的结果一定要是偶数
我们把上面的这个条件带入这个公式
1.两指针之间的距离是奇数
2.链表长度是偶数

2
L(偶数) = C(偶数)*(X+1)-N(奇数);
我们可以发现这个等式不可能成立,奇数乘以偶数一定是奇数
所以这个条件不存在!
N是偶数第一轮就追上了,
N是奇数第一轮追不上,第二轮就追上了。

我们在来看一道题

环形链表II


环形链表II
给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。

不允许修改 链表。

在这里插入图片描述
这是代码

typedef struct ListNode listnode;
struct ListNode *detectCycle(struct ListNode *head) {if(head == NULL){return NULL;}listnode* slow = head;listnode* fast = head;while(fast && fast->next){slow = slow->next;fast = fast->next->next;if(slow == fast){listnode* meet = slow;while(meet!= head){meet = meet->next;head = head->next;}return meet;}}return NULL;
}

关于这个当slow == fast的时候把slow赋值给meet,然后让head从头开始走,当遇到meet的时候就是链表环的入口这个问题,我们也可以分析一下把他写一个等式过来
根据上面的分析
我们得到
slow走的距离是L+N
fast走的距离是L+X*C+N

在这里插入图片描述
相遇时
fast走的距离是slow的两倍
我们可以得到2(L+N) = L+XC+N;
我们化简一下
L+N = X
C;
L = XC-N.
通过这个等式我们可以看到L就等于fast走的链表的圈数,减去slow进环与fast相遇走的距离,圈数减去N之后就是C-N(圈数是大于等于1的整数)其实我们除开x
c就是L = C-N;
那就可以得出一个结论当slow和fast相遇时,剩下的距离就等于从链表开头到链表入环的那个距离
所以就可以设一个meet和head同时往后走当他们两个相遇时就是链表的入环口。
所以就可以用这个方法解决问题。

这篇关于关于链表带环问题为什么要用快慢指针的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/962876

相关文章

Windows环境下解决Matplotlib中文字体显示问题的详细教程

《Windows环境下解决Matplotlib中文字体显示问题的详细教程》本文详细介绍了在Windows下解决Matplotlib中文显示问题的方法,包括安装字体、更新缓存、配置文件设置及编码調整,并... 目录引言问题分析解决方案详解1. 检查系统已安装字体2. 手动添加中文字体(以SimHei为例)步骤

SpringSecurity整合redission序列化问题小结(最新整理)

《SpringSecurity整合redission序列化问题小结(最新整理)》文章详解SpringSecurity整合Redisson时的序列化问题,指出需排除官方Jackson依赖,通过自定义反序... 目录1. 前言2. Redission配置2.1 RedissonProperties2.2 Red

nginx 负载均衡配置及如何解决重复登录问题

《nginx负载均衡配置及如何解决重复登录问题》文章详解Nginx源码安装与Docker部署,介绍四层/七层代理区别及负载均衡策略,通过ip_hash解决重复登录问题,对nginx负载均衡配置及如何... 目录一:源码安装:1.配置编译参数2.编译3.编译安装 二,四层代理和七层代理区别1.二者混合使用举例

怎样通过分析GC日志来定位Java进程的内存问题

《怎样通过分析GC日志来定位Java进程的内存问题》:本文主要介绍怎样通过分析GC日志来定位Java进程的内存问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、GC 日志基础配置1. 启用详细 GC 日志2. 不同收集器的日志格式二、关键指标与分析维度1.

Java 线程安全与 volatile与单例模式问题及解决方案

《Java线程安全与volatile与单例模式问题及解决方案》文章主要讲解线程安全问题的五个成因(调度随机、变量修改、非原子操作、内存可见性、指令重排序)及解决方案,强调使用volatile关键字... 目录什么是线程安全线程安全问题的产生与解决方案线程的调度是随机的多个线程对同一个变量进行修改线程的修改操

Redis出现中文乱码的问题及解决

《Redis出现中文乱码的问题及解决》:本文主要介绍Redis出现中文乱码的问题及解决,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1. 问题的产生2China编程. 问题的解决redihttp://www.chinasem.cns数据进制问题的解决中文乱码问题解决总结

全面解析MySQL索引长度限制问题与解决方案

《全面解析MySQL索引长度限制问题与解决方案》MySQL对索引长度设限是为了保持高效的数据检索性能,这个限制不是MySQL的缺陷,而是数据库设计中的权衡结果,下面我们就来看看如何解决这一问题吧... 目录引言:为什么会有索引键长度问题?一、问题根源深度解析mysql索引长度限制原理实际场景示例二、五大解决

Springboot如何正确使用AOP问题

《Springboot如何正确使用AOP问题》:本文主要介绍Springboot如何正确使用AOP问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录​一、AOP概念二、切点表达式​execution表达式案例三、AOP通知四、springboot中使用AOP导出

Python中Tensorflow无法调用GPU问题的解决方法

《Python中Tensorflow无法调用GPU问题的解决方法》文章详解如何解决TensorFlow在Windows无法识别GPU的问题,需降级至2.10版本,安装匹配CUDA11.2和cuDNN... 当用以下代码查看GPU数量时,gpuspython返回的是一个空列表,说明tensorflow没有找到

解决未解析的依赖项:‘net.sf.json-lib:json-lib:jar:2.4‘问题

《解决未解析的依赖项:‘net.sf.json-lib:json-lib:jar:2.4‘问题》:本文主要介绍解决未解析的依赖项:‘net.sf.json-lib:json-lib:jar:2.4... 目录未解析的依赖项:‘net.sf.json-lib:json-lib:jar:2.4‘打开pom.XM