刷题计划 day4 【双指针、快慢指针、环形链表】链表下
⚡刷题计划day4继续,可以点个免费的赞哦~
下一期将会开启哈希表刷题专题,往期可看专栏,关注不迷路,
您的支持是我的最大动力🌹~
目录
⚡刷题计划day4继续,可以点个免费的赞哦~
下一期将会开启哈希表刷题专题,往期可看专栏,关注不迷路,
您的支持是我的最大动力🌹~
题目一:19. 删除链表的倒数第 N 个结点
法一:计算链表长度
法二:双指针
题目二:面试题 02.07. 链表相交
法一:双指针
法二:合并链表实现同步移动
题目三:142. 环形链表 II
法一:快慢指针法
1.判断链表是否有环
2.如果有环,如何找到环的入口
2.1 n==1
2.2 n>1
法二:哈希表
题目一:19. 删除链表的倒数第 N 个结点
leetcode:19. 删除链表的倒数第 N 个结点
(https://leetcode.cn/problems/remove-nth-node-from-end-of-list/description/)
法一:计算链表长度
常规思路:先遍历得到链表长度L,然后再次遍历到 L-n+1个结点,便是我们需要删除的结点;
这里我们还是使用虚拟头结点统一,于是从虚拟结点开始遍历L-n+1个结点,它的下一个结点便是我们要删除的结点,这样我们只需修改一次指针,就可完成删除操作。
如图辅助理解:

AC代码
class Solution {public ListNode removeNthFromEnd(ListNode head, int n) {ListNode dummyHead = new ListNode();dummyHead.next=head;ListNode cur = dummyHead;int length = getLength(head);for (int i=1;i<length-n+1;i++){cur = cur.next;}if(cur.next!=null){//避免空指针cur.next = cur.next.next;//删除操作}return dummyHead.next;
}public int getLength(ListNode head){int length = 0;while(head != null){length++;head=head.next;}return length;}
}
法二:双指针
主要思路:
要删除倒数第n个,我们可以使用双指针,这样不用去求长度;
保持一个相差n的区间,fast在前,slow在后。这样等fast走到链表末尾,slow对应的就是我们要删除的结点;
因为链表删除我们需要通过前一个结点,所以将相差区间设为n+1,可以结合图理解:

AC代码
class Solution {public ListNode removeNthFromEnd(ListNode head, int n) {ListNode dummyHead = new ListNode();dummyHead.next=head;ListNode fast = dummyHead;ListNode slow = dummyHead;
// 只要快慢指针相差 n 个结点即可for (int i=1;i<=n+1;i++){fast = fast.next;}while (fast!=null){fast = fast.next;slow = slow.next;}
if(slow.next!=null){slow.next = slow.next.next;}return dummyHead.next;}
}
题目二:面试题 02.07. 链表相交
leetcode:面试题 02.07. 链表相交
(https://leetcode.cn/problems/intersection-of-two-linked-lists-lcci/description/)
简单来说,就是求两个链表交点节点的指针。 这里要注意,交点不是数值相等,而是指针相等。
为了方便举例,假设节点元素数值相等,则节点指针相等。
看如下两个链表,目前curA指向链表A的头结点,curB指向链表B的头结点:

我们求出两个链表的长度,并求出两个链表长度的差值,然后让curA移动到,和curB 末尾对齐的位置,如图

此时我们就可以比较curA和curB是否相同,如果不相同,同时向后移动curA和curB,如果遇到curA == curB,则找到交点。
否则循环退出返回空指针。
AC代码
法一:双指针
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {// 初始化两个链表的当前节点ListNode cur1 = headA;ListNode cur2 = headB;// 初始化两个链表的长度int len1 = 0;int len2 = 0;
// 求cur1长度while (cur1 != null) {len1++;cur1 = cur1.next;}// 求cur2长度while (cur2 != null) {len2++;cur2 = cur2.next;}
// 重新初始化两个链表的当前节点cur1 = headA;cur2 = headB;
// 如果第一个链表比第二个短,交换两个链表的头节点和长度if (len1 < len2) {//1. swap (len1, len2);int temp = len1;len1 = len2;len2 = temp;//2. swap (cur1, cur2);ListNode temNode = cur1;cur1 = cur2;cur2 = temNode;}
// 计算长度的差值int gap = len1 - len2;// 移动较长链表的当前节点,使cur1与cur2的末尾位置对齐,看图while (gap-- > 0) {cur1 = cur1.next;}
// 同时遍历两个链表,遇到相同则直接返回while (cur1 != null) {if (cur1 == cur2) {return cur1; // 返回相交的节点}cur1 = cur1.next;cur2 = cur2.next;}
// 如果两个链表没有相交,返回nullreturn null;}
}
法二:合并链表实现同步移动
主要思路:
-
同步移动指针:
-
使用一个
while循环,只要p1和p2没有相遇,就继续移动指针。 -
对于
p1,如果它到达了链表A的末尾(即p1为null),则将它移动到链表B的头部,重新开始遍历。 -
对于
p2,如果它到达了链表B的末尾(即p2为null),则将它移动到链表A的头部,重新开始遍历。
-
-
相遇即相交:
-
当两个指针
p1和p2相遇时,它们指向的就是链表相交的节点。因为两个指针最终都会遍历完两个链表,如果链表有相交点,它们最终会在相交点相遇。
-
-
返回结果:
-
一旦
p1和p2相遇,即它们指向同一个节点,就返回这个节点。
-
public class Solution {public ListNode getIntersectionNode(ListNode headA, ListNode headB) {// p1 指向 A 链表头结点,p2 指向 B 链表头结点ListNode p1 = headA, p2 = headB;while (p1 != p2) {// p1 走一步,如果走到 A 链表末尾,转到 B 链表if (p1 == null) p1 = headB;else p1 = p1.next;// p2 走一步,如果走到 B 链表末尾,转到 A 链表if (p2 == null) p2 = headA;else p2 = p2.next;}return p1;}
}
题目三:142. 环形链表 II
leetcode:142. 环形链表 II
(https://leetcode.cn/problems/linked-list-cycle-ii/description/)

法一:快慢指针法
判断链表是否有环,我们一般可以使用快慢指针法
此题还是有一定难度,考察了对链表环的判断,已经需要进行数学运算,下文会进行详细解释。
对于此题大致分为两大步:
1.判断链表是否有环
2.如果有环,如何找到环的入口
1.判断链表是否有环
分别定义fast,slow指针,fast指针每次移动两个节点,slow指针每次移动一个节点,如果 fast 和 slow指针在途中相遇 ,说明这个链表有环。
2.如果有环,如何找到环的入口
这步已经可以判断链表是否有环了,接下来是寻找环的入口,需要用到一点数学运算。
假设从头结点到环形入口节点 的节点数为x。 环形入口节点到 fast指针与slow指针相遇节点 节点数为y。 从相遇节点 再到环形入口节点节点数为 z。 如图所示:

那么当相遇时:
slow指针走过的节点数为: x + y, fast指针走过的节点数:x + y + n (y + z),n为fast指针在环内走了n圈才遇到slow指针, (y+z)为 一圈内节点的个数A。
加深理解注:
1.fast指针为什么 n (y + z)? 因为fast比slow快,fast进入圈后至少需要一圈后追反超slow,由此也可知道,n>=1(后续解题会用)。
2.为什么slow就不用比如k(y+z)? 因为slow进入圈后在一圈内一定会被fast追上
3.那为什么slow一圈内就一定会被fast追上呢? 可以这样通俗理解:首先fast会比slow快1,如果slow走一圈,fast就会走两圈,那一定会追上。
因为fast指针是一步走两个节点,slow指针一步走一个节点, 所以 slow指针走过的节点数 * 2 = fast指针走过的节点数,所以可以列出方程:
(x + y) * 2 = x + y + n (y + z)
因为我们要找环形入口,即需要找x,将x单独放出来化简:
x = n (y + z) - y
但是我们看一下这个式子呢,也发现不了什么,我们是想通过右边的参数来求x,但发现目前右侧也没啥特殊形式,还有个-y。于是我们可以提一个(y+z)出来,
x = (n - 1) (y + z) + z(此处n>=1,前面有解释)
此时就明了了。
2.1 n==1
当 n为1的时候,公式就化解为 x = z,
这就意味着,从头结点出发一个指针,从相遇节点也出发一个指针,这两个指针每次只走一个节点, 那么当这两个指针相遇的时候就是 环形入口的节点。
也就是在相遇节点处,定义一个指针index1,在头结点处定一个指针index2。
让index1和index2同时移动,每次移动一个节点, 那么他们相遇的地方就是 环形入口的节点。
2.2 n>1
那么 n如果大于1是什么情况呢,就是fast指针在环形转n圈之后才遇到 slow指针。
其实这种情况和n为1的时候效果是一样的,一样可以通过这个方法找到 环形的入口节点,只不过,index1 指针在环里 多转了(n-1)圈,然后再遇到index2,相遇点依然是环形的入口节点。
代码如下:
public class Solution {public ListNode detectCycle(ListNode head) {ListNode fast = head;ListNode slow = head;while(fast!=null && fast.next!=null){fast = fast.next.next;slow = slow.next;
//相遇,有环if(fast==slow){ListNode index1 = fast;ListNode index2 = head;// 两个指针,从头结点和相遇结点,各走一步,直到相遇,相遇点即为环入口while (index1 != index2){index1 = index1.next;index2 = index2.next;}return index1;}
}return null;}
}
法二:哈希表
这个思路就简单很多,时间复杂度:O(N),空间复杂度:O(N);
但第一种双指针的解法也需要掌握,时间复杂度:O(N),空间复杂度:O(1)。
关于哈希表我们下期也会做相应的专题刷题。
主要思路:遍历链表中的每个节点,并将它记录下来;一旦遇到了此前遍历过的节点,就可以判定链表中存在环。借助哈希表可以很方便地实现。
代码:
详细见注解
public class Solution {public ListNode detectCycle(ListNode head) {// 初始化指针pos指向头结点ListNode pos = head;// 使用HashSet来存储已经访问过的节点Set<ListNode> visited = new HashSet<ListNode>();
// 遍历链表while (pos != null) {// 如果当前节点已经被访问过,说明存在环,返回当前节点if (visited.contains(pos)) {return pos;} else {// 否则,将当前节点添加到visited集合中visited.add(pos);}// 移动到下一个节点pos = pos.next;}
// 如果遍历完整个链表都没有发现环,返回nullreturn null;}
}
相关文章:
刷题计划 day4 【双指针、快慢指针、环形链表】链表下
⚡刷题计划day4继续,可以点个免费的赞哦~ 下一期将会开启哈希表刷题专题,往期可看专栏,关注不迷路, 您的支持是我的最大动力🌹~ 目录 ⚡刷题计划day4继续,可以点个免费的赞哦~ 下一期将会开启哈希表刷题…...
最高200万!苏州成都杭州的这些AI政策补贴,你拿到了吗?
随着全球人工智能技术的迅猛发展,地方政府纷纷出台相关政策以抢占未来科技的制高点。苏州 成都 杭州这三个城市更是推出了一系列AI政策补贴,旨在通过多方面支持,推动本地AI产业的发展。本文将带你了解目前不完全统计到的苏州 成都 杭州三地AI…...
使用两台虚拟机分别部署前端和后端项目
使用两台虚拟机分别部署前端和后端项目 1 部署方案2 准备两台虚拟机,并配置网络环境3 部署后端项目3.1 打包服务3.2 上传jar包到服务器3.3 集成Systemd3.3.1 移动端服务集成Systemd3.3.2 后台管理系统集成Systemd 4 配置域名映射5 部署前端项目5.1 移动端5.1.1 打包…...
Halcon学习之derivate_gauss
HALCON 图像处理库中的一个常用算子,用于计算图像的高斯导数。高斯导数是一种平滑导数,在计算过程中结合了高斯滤波,具有平滑噪声的效果。这个算子可以计算图像的不同导数,如梯度、一阶导数、二阶导数、以及 Hessian 行列式等。 …...
智能优化算法(三):遗传算法
文章目录 1.问题描述2.遗传算法2.1.算法概述2.2.编码操作2.3.选择操作2.4.交叉操作2.5.变异操作2.6.算法流程 3.算法实现3.1.MATLAB代码实现3.2.Python代码实现 4.参考文献 1.问题描述 \quad 在利用启发式算法求解问题时,我们常常需要应用遗传算法解决函数最值问题&…...
Docker部署nacos...用户名密码错误
前提 镜像选择v2.3.0版本,因为最新的没拉下来用的别的地方save load的镜像。 官方示例 官方文档 数据库脚本,直接去数据库新建数据库nacos吧,执行脚本,执行完成后,发现只有建表语句,查询得知,…...
搭建Vue开发环境
一、下载Vue.js 进入官网教程安装 — Vue.js (vuejs.org) 下载开发版本到本地 二、安装 Vue Devtools 安装完成后...
富格林:防范虚假可信投资经验
富格林指出,现货黄金投资作为一种全球性的金融衍生品交易,吸引了无数投资者的目光。它不仅具备避险属性,还是资产配置中不可或缺的一部分。然而,要想在市场中防范虚假陷阱,投资者必须要掌握并且利用可信的投资经验。下…...
Intent的数据传递
在Android开发中,使用Intent在Activity之间传递数据是一种常见的方式。然而,Intent确实有一些大小和类型的限制。 Intent的限制 数据大小限制:虽然官方没有明确说明Intent的数据大小限制,但是Intent是通过Binder机制进行IPC&…...
【NPU 系列专栏 3.1 -- - ARM NPU 有哪些型号?】
请阅读【嵌入式及芯片开发学必备专栏】 文章目录 ARM X 系列和 Z 系列 NPU 详解ARM X 系列 NPUARM X 系列 NPU型号和算力ARM X 系列 NPU 应用场景ARM Z 系列 NPU 简介ARM Z 系列 NPU 型号和算力ARM Z 系列 NPU 应用场景SummaryARM X 系列和 Z 系列 NPU 详解 ARM 的 NPU(Neura…...
如何运行别人的vue项目
文章目录 如何运行别人的vue项目一、删除现有的node_modules二、npm换源三、清理缓存四、进行依赖安装五、运行服务器 如何运行别人的vue项目 一、删除现有的node_modules 二、npm换源 换成淘宝的镜像源 查看当前镜像源 npm config get registry更换淘宝镜像源 npm confi…...
【Django5】内置Admin系统
系列文章目录 第一章 Django使用的基础知识 第二章 setting.py文件的配置 第三章 路由的定义与使用 第四章 视图的定义与使用 第五章 二进制文件下载响应 第六章 Http请求&HttpRequest请求类 第七章 会话管理(Cookies&Session) 第八章 文件上传…...
汕头 西月 公司的面试
1;常用的框架,tp 他的特性 2:事务,的使用的场景。 3:redis 的使用的场景 。 4:redis 集合使用的场景...
Spring Boot 实现不同项目之间的远程
Spring Boot 实现不同项目之间的远程调用 在分布式系统中,通常需要多个微服务之间进行通信。在 Spring Boot 中,实现远程调用的方式有很多,常见的方法包括使用 REST API、gRPC、以及 Spring Cloud Feign 等。本篇博客将详细介绍如何在不同的…...
【VS2019安装+QT配置】
【VS2019安装QT配置】 1. 前言2. 下载visual studio20193. visual studio2019安装4. 环境配置4.1 系统环境变量配置4.2 qt插件开发 5. Visual Studio导入QT项目6. 总结 1. 前言 前期安装了qt,发现creator编辑器并不好用,一点都不时髦。在李大师的指导下&…...
敏感信息泄露wp
1.右键查看网页源代码 2.前台JS绕过,ctrlU绕过JS查看源码 3.开发者工具,网络,查看协议 4.后台地址在robots,拼接目录/robots.txt 5.用dirsearch扫描,看到index.phps,phps中有源码,拼接目录,下载index.phps …...
首屏性能优化
* 减少HTTP请求 * 合并css 和 JS 文件, * 图片精灵:将多个小图标合并成一张图片,通过CSS定位显示所需部分 * 内联小型资源:对于一些小的CSS和js代码,直接内联到HTML中 * 优化资源加载 * 延迟加载:对非关…...
HVV | .NET 攻防工具库,值得您拥有!
01阅读须知 此文所提供的信息只为网络安全人员对自己所负责的网站、服务器等(包括但不限于)进行检测或维护参考,未经授权请勿利用文章中的技术资料对任何计算机系统进行入侵操作。利用此文所提供的信息而造成的直接或间接后果和损失…...
angular入门基础教程(九)依赖注入(DI)
依赖注入 Angular 中的依赖注入(DI)是框架最强大的特性之一。可以将依赖注入视为 Angular 在运行时为你的应用 提供所需资源的能力。依赖项可以是服务或其他资源。 使用服务的一种方式是作为与数据和 API 交互的方式。为了使服务可重用,应该…...
小学生也能听得懂的大模型 - Transformer 1
参考 [小学生也能听得懂的大模型 Transformer 1]...
从Markdown到可执行规范:Tessl Framework初探与“规范即源代码”的实践思考
从Markdown到可执行规范:Tessl Framework初探与“规范即源代码”的实践思考 当代码行数不再是衡量开发效率的唯一标准,一种全新的编程范式正在悄然兴起。想象一下,开发者不再需要直接编写实现细节,而是专注于用结构化的自然语言描…...
FPGA实战:手把手教你用Vivado的MMCM IP核动态调整ADC采样时钟相位(附仿真避坑指南)
FPGA实战:Vivado MMCM动态相位调整的工程化实现与深度避坑指南 在高速数据采集系统中,ADC采样时钟相位的精确控制往往是决定信号完整性的关键因素。当FPGA工程师发现采样数据存在周期性抖动或眼图闭合时,动态调整时钟相位便成为优化系统性能的…...
YOLOv8 Face:从技术原理到生产级人脸检测系统构建指南
YOLOv8 Face:从技术原理到生产级人脸检测系统构建指南 【免费下载链接】yolo-face YOLO Face 🚀 in PyTorch 项目地址: https://gitcode.com/gh_mirrors/yo/yolo-face 在当今计算机视觉领域,实时人脸检测技术已成为智能交互、安全监控…...
intv_ai_mk11应用场景:新媒体运营——热点事件评论草稿、标题党生成、互动话术
intv_ai_mk11在新媒体运营中的三大实战应用 1. 新媒体运营的痛点与AI解决方案 新媒体运营人员每天面临三大核心挑战:快速跟进热点事件、创作吸引眼球的标题、设计有效的互动话术。传统人工创作方式不仅耗时耗力,而且难以保证持续高质量输出。 intv_ai…...
51单片机开发环境搭建指南:从Keil5安装到程序烧录全流程
1. 51单片机开发环境搭建全攻略 刚接触51单片机的朋友可能会被一堆陌生的名词搞懵——Keil5、CH340、HEX文件、烧录工具...别担心,我当初也是这样过来的。今天我就用最直白的语言,手把手带你搭建完整的开发环境。整个过程就像组装乐高积木,只…...
PasteMD效果展示:3秒将ChatGPT对话转换为规范技术报告
PasteMD效果展示:3秒将ChatGPT对话转换为规范技术报告 1. 为什么你需要这个工具 你有没有过这样的经历:在ChatGPT里反复调试出一段完美的技术方案,复制粘贴到Word文档时却变成一团乱码?公式显示成一串LaTeX代码,表格错…...
从‘翻车’到稳定:手把手教你用Matlab极点配置驯服小车倒立摆(附Simulink模型)
用Matlab极点配置实现小车倒立摆的精准控制:从理论到Simulink实战 倒立摆系统作为控制理论中的经典案例,完美展现了动态系统稳定控制的挑战与魅力。想象一下,一根垂直向上的杆子放在移动小车上,任何微小的扰动都会导致杆子倾倒——…...
基于SpringBoot + Vue的校园流浪动物救助平台
文章目录前言一、详细操作演示视频二、具体实现截图三、技术栈1.前端-Vue.js2.后端-SpringBoot3.数据库-MySQL4.系统架构-B/S四、系统测试1.系统测试概述2.系统功能测试3.系统测试结论五、项目代码参考六、数据库代码参考七、项目论文示例结语前言 💛博主介绍&#…...
程序员副业指南:CSDN变现全攻略
程序员副业图谱:CSDN技术变现路径分析核心逻辑 围绕技术变现场景构建结构化框架,从技术栈适配性、市场需求匹配度、时间投入产出比三个维度建立评估模型技术咨询类副业路径技术问答悬赏CSDN问答模块的答题变现机制高价值技术领域识别(云原生/…...
智能电动汽车芯片全景解析:从MCU到SoC的技术跃迁
1. 智能电动汽车的芯片革命:从机械控制到数字大脑 十年前打开汽车引擎盖,看到的是一堆机械部件和少量电子控制单元;现在掀开一辆特斯拉的"前备箱",映入眼帘的却是布满芯片的电路板。这个直观变化背后,是汽车…...
