非常简单就能理解的 链表带环问题 你也能轻松学会!

news/2024/9/20 10:28:48

文章目录

  • 判断链表是否带环
  • 若链表带环找出环的入口
  • 其他高频的面试问题

判断链表是否带环

题目描述:

给定一个链表,判断链表中是否有环。

在这里插入图片描述

思路

可以明确的是:若一个链表带环,那么用指针一直顺着链表遍历,最终会回到某个地方。
 我们可以定义两个指针(快慢指针),两个指针均从表头开始同时遍历链表,快指针一次走两步,慢指针一次走一步。如果链表带环,那么快慢指针一定会相遇,否则快指针会先遍历完链表(遇到NULL)

 若是你不明白为什么链表带环,快慢指针就一定会相遇,那么你可以想想龟兔赛跑:
在这里插入图片描述

代码示例:

struct ListNode {int val;struct ListNode *next;
};
bool hasCycle(struct ListNode *head) {struct ListNode* slow = head;struct ListNode* fast = head;while (fast && fast->next){fast = fast->next->next;//兔子走两步slow = slow->next;//乌龟走一步if (fast == slow)//兔子与乌龟相遇return true;}return false;
}

若链表带环找出环的入口

题目描述:

给定一个链表,返回链表开始入环的第一个结点。如果链表无环,则返回NULL。

这不是一道简简单单的代码题,严格来说,这是一道数学推论题,若是不能得出最终推论,是不能很好的解决该问题的。

推论如下:

在这里插入图片描述

解释:

假设快指针走两步,慢指针走一步。头节点到入环结点距离为L,环入口结点 到快慢指针相遇结点距离为X,环的长度为C。
当快慢指针相遇,快慢指针走的距离: 慢指针:L+X 快指针:L+NC+X(N为快指针围着环走的圈数)
为什么有个N,假设环C很小,L很长,快指针可能在里面转了很多圈了。
然后就会有:2
(L+X)=L+NC+X(2倍慢指针走的距离就是快指针走的距离,因为快指针走的步数时慢指针的两倍) 所以就有:
L+X=N
C —> L=N*C-X
所以求环链表入环结点思路有:当快慢指针相遇时,让一个指针指向链表头,然后一起一个节点一个结点走,一定会在入口结点相遇。

代码示例:

struct ListNode {int val;struct ListNode *next;
};
struct ListNode *detectCycle(struct ListNode *head) {struct ListNode* fast = head;struct ListNode* slow = head;while (fast && fast->next){slow = slow->next;//慢指针走一步fast = fast->next->next;//快指针走两步if (fast == slow)//相遇{struct ListNode* meet = fast;//相遇点while (head != meet){head = head->next;//一个指针从出发点开始走meet = meet->next;//一个指针从相遇点开始走}return meet;//两个指针相遇,返回当前结点}}return NULL;//链表不带环
}

其他高频的面试问题

问题一:为什么慢指针走一步,快指针走两步,他们一定会在环里面相遇?会不会永远追不上?请证明。

不会永远追不上,证明如下:
在这里插入图片描述

当快慢指针都进环了,假设快慢指针间的距离为N,当快慢指针走一步,他们之间的距离就缩短了1,再走一步就缩短了2…最后肯定他们之间的距离会缩短到0。

问题二:那么慢指针走一步,快指针走三步?走四步?或是走n步行不行?为什么?请证明。

不行,这样可能会追不上,证明如下:

在这里插入图片描述

解释:

假设快指针走3步,慢指针走1步。当快慢指针都进环后,假设快慢指针间的距离为N,环的周长是C,当快慢指针走一步,他们之间的距离就缩短了2,再走一步,快慢指针之间交开始的距离缩短了4。
分俩种情况:
1.若N为偶数,则他们之间的距离最终会减为0,即相遇。
2.若N为奇数,则他们之间的距离会减到1,然后减到-1,也就意味着他们之间的距离又变为了C-1,此时又分俩种情况:
1> 若C为奇数,则C-1为偶数,因为他们之间的距离一次缩小2,所有他们会相遇。
2> 若C为偶数,则C-1还是为奇数,也就是说他们之间的距离还是奇数,他们永远不会相遇。

当慢指针走一步,快指针走四步或是走n步时,证明过程类似,在此就不做赘述。


https://dhexx.cn/news/show-4633866.html

相关文章

集成测试方法详细教程及实现方法

集成测试是一种软件测试方法,用于验证不同组件、模块或系统之间的交互和集成。它的目标是检测和解决在组件集成过程中可能出现的问题,确保各个组件在协同工作时正常运行。 具体来说,集成测试关注以下几个方面: 1. 接口测试&#x…

【linux下一次复制cp多个文件】

linux下一次复制cp多个文件 linux cp 参数说明 -a:此选项通常在复制目录时使用,它保留链接、文件属性,并复制目录下的所有内容。其作用等于dpR参数组合。 -d:复制时保留链接。这里所说的链接相当于Windows系统中的快捷方式。 -f&…

nginx系统优化和内核优化

nginx系统优化 一:隐藏nginx版本号 方法一:修改配置文件 vim /usr/local/nginx/conf/nginx.confnginx -t systemctl restart nginx curl -I http://192.168.52.108方法二:修改源代码 vim /opt/nginx-1.24.0/src/core/nginx.h ##配置文件里…

Yolov8轻量级:Next-vit,用于现实工业场景的下一代视觉 Transformer

1.Next-vit介绍 论文:https://arxiv.org/pdf/2207.05501.pdf 由于复杂的注意力机制和模型设计,大多数现有的视觉 Transformer(ViT)在现实的工业部署场景中不能像卷积神经网络(CNN)那样高效地执行。这就带来了一个问题:视觉神经网络能否像 CNN 一样快速推断并像 ViT 一样…

【嵌入式烧录/刷写文件】-2.9-Intel Hex文件的地址对齐Address Alignment

案例背景(共5页精讲): 对一个Intel Hex文件,进行地址对齐Address Alignment。 目录 1 为什么要进行“地址对齐Address Alignment” 1.1 “对齐长度”的选择 2 使用Vector HexView工具对Hex文件进行“地址对齐Address Alignment” 2.1 “自动”完成“地址对齐Ad…

一文搞懂位运算

一,原码、反码、补码 接下来我们主要介绍十进制数用二进制表示的不同方法,所以为了简洁,我们用一个字节,也就是8个bit来表示二进制数。 1,原码 十进制 原码 2 0000 0010 -2 1000 0010 原码其实是最容易理解的&…

docker cgroup资源占用及docker的镜像创建

cgroup用来资源限制 包括cpu,内存,磁盘三大方面 基本复写了常见的资源配额和使用量控制 cgroup是controlgroup的缩写 设置cpu使用率的上限 linux通过cfs(完全公平调度器)来调度各个进程对cpu的使用,cfs默认的调度…

K8s in Action 阅读笔记——【11】Understanding Kubernetes internals

K8s in Action 阅读笔记——【11】Understanding Kubernetes internals 11.1 Understanding the architecture Kubernetes集群分为两个部分: k8s控制平面工作节点 控制平面的组件 构成控制平面的组件有: etcd:etcd是一个分布式的持久化键…

Tomcat部署及多实例部署

Tomcat部署及多实例部署 一、什么是Tomcat二、Tomcat核心组件1.什么是servlet2.什么是 JSP 三、Tomcat 功能组件结构1.Connector2.Container2.1Container 包含四个子容器 3.Service 四、Tomcat 请求过程五、Tomcat 服务部署1.关闭防火墙2.上传jdk包,查看jdk版本&…

zerotier使用

目标 使用zerotier进行内网穿透,使外网客户端访问内网服务器 步骤 1.1 注册 进入zerotier官网,注册 ​ 完成后进入个人中心,点击networks,选择创建网络,得到一个networkid ​ 点击id进入设置,编辑名称…