LeetCode(4)-链表:快慢指针

freemarker_常用内置函数 freemarker_常用内置函数 freemarker_常用内置函数 立即下载

文章目录

 

链表中有一个很常用的技巧被称为快慢指针技巧,通常用于找到中间节点和用于解决一些具有环状链表性质的问题

LeetCode 876.链表的中间节点

给定一个带有头结点 head 的非空单链表,返回链表的中间结点。
如果有两个中间结点,则返回第二个中间结点。
示例 1:
输入:[1,2,3,4,5]
输出:此列表中的结点 3 (序列化形式:[3,4,5])
返回的结点值为 3 。 (测评系统对该结点序列化表述是 [3,4,5])。
注意,我们返回了一个 ListNode 类型的对象 ans,这样:
ans.val = 3, ans.next.val = 4, ans.next.next.val = 5, 以及 ans.next.next.next = NULL.
示例 2:
输入:[1,2,3,4,5,6]
输出:此列表中的结点 4 (序列化形式:[4,5,6])
由于该列表有两个中间结点,值分别为 3 和 4,我们返回第二个结点。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/middle-of-the-linked-list
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

其实这个问题有两种解法,一种是使用快慢指针,另一种比较容易想到的是使用计数法,先说说用计数法如何解决这个问题:

首先遍历一遍链表,确定链表长度len,在下一个循环中定义迭代len / 2 次即可找到中间节点了:

代码实现:

public ListNode middleNode(ListNode head) {
        if (head == null) return null;
        int len = 0;
        ListNode counter = head;
        while (counter != null) {
            len++;
            counter = counter.next;
        }
        System.out.println(len);
        for (int i = 0; i < len / 2; i++) {
            head = head.next;
        }
        return head;
    }

使用计数法需要遍历一次链表,时间复杂度为O(n), 然后还需要再次进行len/2次迭代,时间复杂度为O(n/2),所以总时间复杂度为O(n) + O(n/2) = O(n).下面介绍一下什么是快慢指针.

如果用快慢指针解决这个问题的话.在一开始就需要定义两个指针,一个被称为慢指针slow,一个被称为快指针fast;快指针的前进速度是慢指针的前进速度的两倍,那么当快指针到达链表尾部时,慢指针就正好在链表的中间了:

public ListNode middleNode(ListNode head) {
        ListNode slow = head;
        ListNode fast = head;
        while (fast != null && fast.next != null) {
            slow = slow.next;
            fast = fast.next.next;
        }
        return slow;
    }

LeetCode 19. 删除链表的倒数第N个节点

给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。
示例:
给定一个链表: 1->2->3->4->5, 和 n = 2.
当删除了倒数第二个节点后,链表变为 1->2->3->5.
说明:
给定的 n 保证是有效的。
进阶:
你能尝试使用一趟扫描实现吗?
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

使用快慢指针的思路是这样子的:
1.定义cur指向head,并且定义nFast是cur的后n个节点
2.当nFast不为null时,cur和nFast都向后走一步
3.当nFast为null时,cur即为倒数第n个节点
4.将cur的前一个节点和cur的下一个节点相连,且让cur.next=null即完成了对cur的删除
 

代码实现:

public ListNode removeNthFromEnd(ListNode head, int n) {
        if (head == null) return null;
        ListNode pre = null;
        ListNode cur = head;
        ListNode nFast = cur;
        for (int i = 0; i < n && nFast != null; i++) {
            nFast = nFast.next;
        }
        //找到需要删除的节点
        while (nFast != null) {
            pre = cur;
            cur = cur.next;
            nFast = nFast.next;
        }
        //删除节点
        if (pre != null) {
            pre.next = cur.next;
            cur.next = null;
            return head;
        }
        //被删除的是链头
        return head.next;
    }

LeetCode 141. 环形链表

给定一个链表,判断链表中是否有环。
为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。
示例 1:
输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点。
示例 2:
输入:head = [1,2], pos = 0
输出:true
解释:链表中有一个环,其尾部连接到第一个节点。
示例 3:
输入:head = [1], pos = -1
输出:false
解释:链表中没有环。
进阶:
你能用 O(1)(即,常量)内存解决此问题吗?
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/linked-list-cycle
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解决思路有很多种,第一种比较好想到的是采用哈希表存储每一个经过的节点地址,当有重复的节点地址时,则说明存在环,但是题目要求使用O(1)的空间复杂度解决问题,那么说明不能使用哈希表存储每个节点;所以可以考虑使用快慢指针法去解决这个问题:

我们可以列举一个生活中的场景,在一个直线型跑道上,博尔特和我一起跑100m,虽然我一定会输给他,但是我一定也可以到达终点(虽然慢了很多);但是如果我们两个人在一个400m的圆形跑道上跑由于博尔特太快了,他一定会在某一圈和我重合在一起,这就是本题能够运用快慢指针的原因:我是那个慢指针,而博尔特是那个快指针:

代码实现:

 public boolean hasCycle(ListNode head) {
        ListNode slow = head;
        ListNode fast = head;
        while (true) {
            slow = (slow == null) ? null : slow.next;
            fast = (fast == null || fast.next == null) ? null : fast.next.next;
            //都到达了终点
            if (slow == null && fast == null) return false;
            //快指针追上慢指针
            if (slow == fast) return true;
        }
    }

不定期更新, 未完持续…

从零开始:IBM V3700控制器更换与机器代码升级全流程指南 本文详细介绍了IBM V3700存储系统控制器更换与机器代码升级的全流程指南。从前期准备、硬件更换到版本同步,逐步解析如何应对503错误等常见问题,确保系统稳定运行。通过实战案例和优化建议,帮助工程师高效完成维护任务,提升存储系统可用性。 阅读详情

相关推荐

CMOS传输门(互补开关)实战指南 | 设计优化 + 常见问题解析

本文深入解析CMOS传输门(互补开关)的设计优化与常见问题,涵盖导通特性、版图设计、高频应用及混合信号设计等关键领域。通过实测数据和优化技巧,帮助工程师解决衬底连接、信号完整性等实际问题,提升数字和模拟混合信号设计的效率与可靠性。

weixin_29229989的博客 164

FreeMarker常用函数

1.去除首尾空格 ${' abc '?trim} 输出结果:abc 2.首字母大写,全部小写,全部大写 首字母大写 ${'abc'?cap_first} 输出结果:Abc 全部小写 ${'AbC'?lower_case} 输出结果:abc 全部大写 ${'abc'?upper_case} 输出结果:ABC 3.定义数组 方式1. <#assign nums=["1","2","3"]/> 方式2. <#assign nums=1..10/> 4.直接遍历 <#list

qq504740598的博客 2633

SpeedyBee F405 V3 50A飞塔装机全攻略:从开箱到首飞避坑指南

本文提供SpeedyBee F405 V3 50A飞塔的详细装机指南,涵盖从开箱检查、硬件焊接、软件配置到安全首飞的全流程。重点剖析了电源连接、固件刷写等高频故障点,帮助FPV新手避开常见陷阱,确保一次成功组装并安全起飞。

weixin_29179311的博客 417

LeetCode刷题总结

常见的算法,主要是以下几种: 基础技巧:分治、二分、贪心 排序算法:快速排序、归并排序、计数排序 搜索算法:回溯、递归、深度优先遍历,广度优先遍历,二叉搜索树等 图论:最短路径、最小生成树 动态规划:背包问题、最长子序列 数据结构,主要有如下几种: 数组与链表:单 / 双向链表 栈与队列 哈希表 堆:最大堆 / 最小堆 树与图:最近公共祖先、并查集 字符串:前缀树(字典树) ...

destiny的专栏 517

Windows下MMdetection3D保姆级安装指南(含CUDA和PyTorch版本避坑)

本文提供Windows平台下MMdetection3D的完整安装指南,重点解决CUDA与PyTorch版本匹配问题。从环境准备到关键组件安装,详细介绍了CUDA Toolkit选择策略、PyTorch精准安装步骤,以及MM系列组件的安装顺序和常见错误解决方案,帮助用户顺利完成3D目标检测环境的配置。

weixin_42628941的博客 493

华为OD机试真题 新系统 2026-04-26 Python&JS 实现【最大化游戏试玩资格分发】

新研发了一台游戏设备可以面向用户接受试玩。现有 n 个试玩申请,每个试玩有开始时间和结束时间。作为协调员,为了能让更多人体验到游戏,你需要对试玩申请进行选择,使得:

MISAYAONE的博客 292

Freemarker函数

Freemarker定义了很多内置函数,用户也可以自定义函数,函数的调用使用? 字符串函数 substring:截取子字符串的函数,类似Java的String.substring字符串函数 $(“abcdef”?substring(n) } 截取字符串n位置开始到结尾,n大于等于0,小于等于字符串的长度 $(“abcdef”?substring(m,n) } 截取字符串m位置开始到n位置,m,n...

qixiang_chen的博客 3237

免杀思路总结

免杀思路总结 1.免杀技术简介 1.免杀的重要性 2.免杀的难度 3.杀毒软件的排行 国外 国内 1 、Bitdefender 1、360 2 、Norton 360 2、智量安全(没测过,据说很厉害) 3 、Kaspersky 3、火绒安全 4 、Webroot 4、金山独霸 5 、Trend Micro 5

LiBai'S BLOG 1万+

Freemarker基本语法

总结来说,要使用Freemarker生成静态文件,你可以使用Java程序调用Freemarker进行渲染并输出到文件,或者结合静态网站生成器进行生成。1.使用Java程序调用Freemarker:你可以编写一个Java程序,使用Freemarker来渲染模板,并将渲染结果输出到文件。需要注意的是,指令的结束标签是必须的,在循环体内部的内容将被迭代多次。除了内建函数,Freemarker还支持自定义函数,可以在模板中使用自己定义的函数来进行特定的处理。操作符来连续访问键。

m0_61898915的博客 3206

【学习系列】SAP RAP 22:Excel文件上传和读取(非扩展&扩展方式)

本文介绍了在RAP中实现Excel文件上传处理的三种方法:1) 使用@Semantics.largeObject注解实现简单上传下载,但限制在ObjectPage页面使用;2) 通过自定义action弹窗实现上传功能,但存在无法自动刷新列表等限制;3) 结合CustomUIExtension实现更灵活的完整功能,但需要UI5开发技能。文章详细说明了每种方法的实现步骤,包括数据库表设计、注解配置、前端界面开发和后端处理逻辑,并比较了各自的优缺点。最后通过一个处理不同币种数据的示例,展示了如何实现业务处理逻辑。

DeveloperMrMeng的博客 628

Dify智能体开发:大语言模型(LLM)问题分类

通过定义分类描述,问题分类器能够根据用户输入,使用 LLM 推理与之相匹配的分类并输出分类结果,向下游节点提供更加精确的信息。

王国平的博客 2253

leetcode刷题知识点总结(刷题必备)

leetcode刷题知识点总结(刷题必备)

ingenuou_的博客 3131

Python爬虫实战:如何爬取京东商品评论数据

在本文中,我们介绍了如何使用 Python 爬虫技术爬取京东商品的评论数据。首先,我们分析了京东商品评论的 API 接口和 JSON 数据结构,然后编写了爬虫程序来抓取评论数据,并将数据保存到 CSV 文件中。接着,我们进行了一些基本的数据分析,包括评分分布和简单的情感分析。爬取京东商品评论的数据可以为电商分析、情感分析等提供有价值的信息。你可以在此基础上进行更深入的分析,挖掘更多的商业价值。希望本篇教程能够帮助你了解如何利用 Python 进行电商数据的爬取和分析!

2201_76125261的博客 1648

LeetCode二刷记录【4】链表的快慢指针和递归法

用于解决单向链表问题的两种技巧,其中快慢指针适合找到链表中端,递归法实际应用了栈的“颠倒顺序”的作用。 具体参考LeetCode回文链表: 快慢指针: class Solution { public: bool isPalindrome(ListNode* head) { //快慢指针,配合链表翻转 if(head==NULL...

qq_32040321的博客 211

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

LeetCode Day4--链表(递归、快慢指针)

当然,n也可以不取1,就表示index2从起始点到入口处的过程中,index1从相遇点开始走,走了n-1圈后,再走距离z,就可以在入口处与index2相遇(注意:index1和index2速度相同,都为1步)。在相遇时,慢指针slow走了x+y步,快指针fast走了x+n(y+z)+y步(n为快慢指针相遇前快指针在环内走了n圈,n>=1),以上为路程,而它们的速度分别为1和2,由于二者走了相同时间,不过,我在自己做的时候没有用虚拟头结点,然后它就一直显示超时,我也不知道是什么原因。的话,应该挺容易的。

qq_66279344的博客 565

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

LeetCode hot 力扣热题100 排序链表

对拆分后的两部分链表分别递归调用 sortList,直到链表被拆分为单个节点(此时链表自然是有序的)。• 最终 [2 -> 4] 和 [1 -> 3] 合并为 [1 -> 2 -> 3 -> 4]。(Merge Sort)在链表上的应用,通过递归的方式将链表分割成两个部分,然后排序并合并。:使用双指针逐个比较两个链表的节点值,将较小值的节点连接到新链表上,直到其中一个链表为空。• 调用 middleNode:链表被分为 [4 -> 2] 和 [1 -> 3]。// 链表为空或只有一个节点,无需排序。

qq_51956059的博客 1067

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

LeetCode Hot 100 | 链表(上)· 基础操作(C++ 题解)

题号题目难度核心技巧时间复杂度空间复杂度160相交链表🟢 简单双指针互换链表头O(m+n)O(1)206反转链表🟢 简单三指针迭代原地反转O(n)O(1)234回文链表🟢 简单快慢指针找中点 + 反转后半段O(n)O(1)141环形链表🟢 简单快慢指针 Floyd 判环O(n)O(1)链表双指针的三种经典模型:同步等长:两指针走相同步数,利用路径总长相等消除差异(160)快慢指针找中点:快 2 慢 1,快指针到尾时慢指针在中间(234)

jcm0903的博客 427

代码随想录算法训练营 DAY4 |链表(交换、快慢指针与环形检测)

如果说昨天的链表练习是入门,那今天就是真正的进阶了。今天的任务列表充满了经典的难题,每道题都像一个精巧的谜题,解开它不仅需要代码能力,更需要巧妙的算法思维。指针的交错飞舞,让我深刻感受到了链表的魅力。: 给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。今天的练习让我对链表的理解又上了一个台阶。的各种高级应用,尤其是在快慢指针和环形链表上的应用,非常烧脑但收获巨大。: 给定一个链表,返回链表开始入环的第一个节点。链表章节的总结,我也会参考 Carl 哥的文章,整理出自己的框架。

m0_54812357的博客 926

19. 删除链表的倒数第 N 个结点(Leetcode刷题 快慢双指针法)

19. 删除链表的倒数第 N 个结点(Leetcode刷题 快慢双指针法) 文章目录19. 删除链表的倒数第 N 个结点(Leetcode刷题 快慢双指针法)题目示例解题思路解题代码代码执行效率 题目 给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。 进阶:你能尝试使用一趟扫描实现吗? 示例 输入:head = [1,2,3,4,5], n = 2 输出:[1,2,3,5] 输入:head = [1], n = 1 输出:[] 输入:head = [1,2], n = 1 输出

lunan的博客 133

快慢指针原理剖析

快慢指针剖析

weixin_65743593的博客 418

力扣算法面试150题——链表——个人笔记

141. 环形链表。

JinYcY的博客 341

代码随想录算法训练营Day4| LeetCode 24 两两交换链表中的节点、19 删除链表的倒数第N个结点、160 相交链表、142 环形链表 II

代码随想录跟练第四天!

修炼途中的所见所闻,所思所想。 389

leetcode143. 重排链表

传送门 题目:给定一个单链表 L:L0→L1→…→Ln-1→Ln 将其重新排列后变为: L0→Ln→L1→Ln-1→L2→Ln-2→… 你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。 给定链表 1->2->3->4, 重新排列为 1->4->2->3. 给定链表 1->2->3->4->5, 重新排列为 1->5->2->4->3. 用快慢指针把链表分成两半,把后半段倒序,然后后半段按顺序插入前半

lonelyVM的博客 274

链表的中间结点 C语言 leetcode876题

给定一个头结点为head的非空单链表,返回链表的中间结点。 如果有两个中间结点,则返回第二个中间结点。

kim的博客 130

LeetCode Algorithm 剑指 Offer 22. 链表中倒数第k个节点

力扣 链表中倒数第k个节点

qq_51570936的博客 166

【力扣hot100】链表专题下|138、148、23、146

本文介绍了三道链表相关问题的解法: 138. 随机链表的复制:通过两次遍历链表,第一次建立新旧节点映射关系,第二次利用映射表连接新节点的next和random指针。 148. 排序链表:使用归并排序方法,先通过快慢指针找到中点分割链表,再递归排序并合并两个有序子链表。 23. 合并K个升序链表:提供两种解法: 暴力解法:按顺序逐个合并链表 优化解法:采用两两合并策略,每次将相邻链表合并后形成新数组,重复直到只剩一个链表 这些解法展示了链表操作中的常见技巧,包括映射表使用、快慢指针、递归分治和归并排序等。

2401_87144364的博客 171
上一篇: LeetCode(3)-链表:反转
下一篇: MySQL基础笔记(2)-连接查询
BoringRong
BoringRong 领域专家: 后端开发技术领域 领域专家: 后端开发技术领域
博客等级 码龄9年 2万+粉丝 386原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BoringRong

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值