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

876. 链表的中间结点

目录

题目链接:

题目:

解题思路:

代码:

总结:


题目链接:

876. 链表的中间结点 - 力扣(LeetCode)

题目:

解题思路:

使用快慢指针,慢的每次走一步,快的一次走两步,这样就可以快的走完,慢的走一半即可

本文介绍了使用快慢指针算法解决「876.链表的中间结点」问题。通过设置两个指针(快指针每次走两步,慢指针每次走一步),当快指针到达链表末尾时,慢指针刚好位于中间位置。这种方法只需一次遍历即可找到中间结点,时间复杂度为O(n),空间复杂度为O(1)。文章详细解析了算法原理、代码实现,并通过示例验证正确性,最后讨论了算法变体和其他应用场景。

代码:

/*** Definition for singly-linked list.* public class ListNode {*     int val;*     ListNode next;*     ListNode() {}*     ListNode(int val) { this.val = val; }*     ListNode(int val, ListNode next) { this.val = val; this.next = next; }* }*/
class Solution {public ListNode middleNode(ListNode head) {ListNode dummy=new ListNode(0,head);ListNode fast=dummy,slow=dummy;while(fast.next!=null&&fast.next.next!=null){fast=fast.next.next;slow=slow.next;}return slow.next;}
}

总结:
 

上面看懂下面不用看

详解「876. 链表的中间结点」解法:快慢指针的妙用
在链表的诸多操作中,寻找中间结点是一个经典问题。本题要求我们找出单链表的中间结点,若有两个中间结点则返回第二个。这一问题可以通过快慢指针这一巧妙的技巧高效解决,下面我们从问题分析、算法原理、代码详解、复杂度分析等多个维度进行深入讲解。
问题背景与分析
在单链表中,结点的访问只能从头部开始依次向后遍历。如果采用朴素的方法,我们需要先遍历整个链表获取长度 n,再遍历到 n/2 的位置找到中间结点。这种方法的时间复杂度是 O(n),但需要两次遍历链表。
而快慢指针技术可以让我们仅用一次遍历就找到中间结点,大大优化了时间效率。其核心思想是:两个指针同时从链表头出发,快指针每次走两步,慢指针每次走一步。当快指针走到链表末尾时,慢指针恰好位于中间位置。
算法原理:快慢指针的工作机制
我们可以将快慢指针的运动过程类比为两个人在赛道上跑步:快指针是 “快跑者”,每次跑两步;慢指针是 “慢跑者”,每次跑一步。当快跑者到达终点时,慢跑者的位置就是赛道的中间点。
对于链表的不同长度,快慢指针的表现如下:
若链表长度为奇数(如示例 1 中的 5 个结点):快指针最终会指向最后一个结点(fast.next == null),此时慢指针指向正中间的结点。
若链表长度为偶数(如示例 2 中的 6 个结点):快指针最终会指向倒数第二个结点(fast.next.next == null),此时慢指针指向第一个中间结点,再往后走一步就是第二个中间结点(题目要求返回的结果)。
代码逐行详解
首先看完整代码:
java
运行
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode middleNode(ListNode head) {
        ListNode dummy = new ListNode(0, head);
        ListNode fast = dummy;
        ListNode slow = dummy;
        while (fast.next != null && fast.next.next != null) {
            fast = fast.next.next;
            slow = slow.next;
        }
        return slow.next;
    }
}
步骤 1:哑结点(Dummy Node)的创建
java
运行
ListNode dummy = new ListNode(0, head);
哑结点是链表操作中常用的技巧,它的val可以是任意值(这里设为 0),next指向链表的头结点head。引入哑结点的目的是统一奇数和偶数长度链表的处理逻辑,避免对链表头结点的特殊判断。
步骤 2:初始化快慢指针
java
运行
ListNode fast = dummy;
ListNode slow = dummy;
我们将快指针fast和慢指针slow都初始化为哑结点dummy,让它们从同一 “起点” 出发。
步骤 3:快慢指针的遍历循环
java
运行
while (fast.next != null && fast.next.next != null) {
    fast = fast.next.next;
    slow = slow.next;
}
循环的条件是fast.next != null && fast.next.next != null,这保证了快指针每次能 “走两步”:
fast.next != null:确保快指针当前结点的下一个结点存在,避免fast.next.next出现空指针异常。
fast.next.next != null:确保快指针能再走一步(即两步操作的第二步有效)。
在循环内部:
fast = fast.next.next;:快指针每次移动两步。
slow = slow.next;:慢指针每次移动一步。
步骤 4:返回中间结点
java
运行
return slow.next;
当循环结束时,慢指针slow的下一个结点就是我们要找的中间结点:
若链表长度为奇数,循环结束时fast.next.next == null,slow指向中间结点的前一个结点,slow.next即为中间结点。
若链表长度为偶数,循环结束时fast.next.next == null,slow指向第一个中间结点的前一个结点,slow.next即为第二个中间结点(符合题目要求)。
测试用例验证
我们结合题目中的示例来验证代码的正确性。
示例 1:输入链表 [1,2,3,4,5](长度为 5,奇数)
初始化:dummy(0)->1->2->3->4->5,fast和slow都指向dummy。
第一次循环:fast.next=1、fast.next.next=2 非空,执行fast=3,slow=1。
第二次循环:fast.next=4、fast.next.next=5 非空,执行fast=5的下一个结点(即null的下一个,这里实际是fast.next=5,fast.next.next=null),循环结束。
此时slow指向2,slow.next指向3,与示例输出一致。
示例 2:输入链表 [1,2,3,4,5,6](长度为 6,偶数)
初始化:dummy(0)->1->2->3->4->5->6,fast和slow都指向dummy。
第一次循环:fast.next=1、fast.next.next=2 非空,执行fast=3,slow=1。
第二次循环:fast.next=4、fast.next.next=5 非空,执行fast=5的下一个结点6,slow=2。
第三次循环:fast.next=6、fast.next.next=null,循环结束。
此时slow指向3,slow.next指向4,与示例输出一致。
复杂度分析
时间复杂度:O(n),其中n是链表的长度。快指针最多遍历到链表末尾,慢指针随之移动,整个过程仅需一次遍历。
空间复杂度:O(1),只使用了常数个额外的指针(dummy、fast、slow),没有使用额外的线性空间。
拓展与思考
变体问题:返回第一个中间结点
如果题目要求 “若有两个中间结点则返回第一个”,我们该如何修改代码?
只需调整返回值为slow即可。以示例 2 为例,循环结束时slow指向3,直接返回slow就能得到第一个中间结点。
修改后的关键代码:
java
运行
return slow;
快慢指针的其他应用
快慢指针技术在链表问题中应用广泛,例如:
判断链表是否有环:快指针每次走两步,慢指针每次走一步,若两指针相遇则链表有环。
寻找链表的倒数第 k 个结点:快指针先走 k 步,然后快慢指针一起走,快指针走到末尾时,慢指针指向倒数第 k 个结点。
总结
本题通过快慢指针技术,仅用一次遍历就高效解决了链表中间结点的查找问题。核心思路是利用快指针和慢指针的速度差,让快指针到达链表末尾时,慢指针恰好位于中间位置。这种方法的时间复杂度是O(n),空间复杂度是O(1),是解决该问题的最优方案。
在实际开发中,快慢指针的思想也可以迁移到其他类似的 “位置查找” 问题中,掌握这一技巧能帮助我们更高效地处理链表相关的算法题。

http://www.dtcms.com/a/581412.html

相关文章:

  • 排序算法:堆排序、快速排序、归并排序
  • qData 数据中台开源版 v1.0.7 发布:新增 SQL Server 支持,快速部署支持达梦与 MySQL 主库切换!
  • Qt 自定义加载动画控件:带文字提示的等待 spinner 实现
  • 织梦做淘宝客网站视频教程移动互联网开发找工作
  • Vue3 任务管理器(Pinia 练习)
  • 没有域名可以做网站吗个人网页设计绘画作品
  • 百胜软件做客华为云生态直播间:全渠道中台如何赋能零售数字化与全球布局?
  • 航电系统架构演进与要点概述
  • 华为云ELB
  • 医疗智能体(eiHealth) 3.4.0 使用指南(for 华为云Stack 8.5.0) 0. 华为除了这个 还有医疗 和生信方面的 产品
  • 写作教学网站wordpress 管理员账号在哪里查询
  • 完善服务终端:一洽对话结束与异常场景提示语设置
  • 从阿里云大模型服务平台百炼看AI应用集成与实践
  • 【图像处理】图像的基础几何变换
  • uniapp + uni-ui + vue3转cli
  • 户外保险网站wordpress icon 插件
  • config.json 完全指南:项目配置的核心实践
  • 【App开发】ADB 详细使用教程- Android 开发新人指南
  • 如何提高网站访客数重庆关键词排名首页
  • 天猫、飞猪打通了迪士尼会员权益 IP 商业化迈入“全域变现”时代
  • 第八章 惊喜22 批判性思维
  • wordpress主题模板视频网站模板实搜网站建设
  • 第1章 SLAM技术导论
  • 测试之bug篇
  • 万全县城乡建设网站企业网站建设的目的是什么
  • 网站建设资源平台地方门户网站的分类
  • VS + Qt 开发多语言,中英文
  • 游戏开发入门,简单小游戏原理-关于2D渲染的一些小想法
  • Bootstrap4 徽章(Badges)
  • CSE(ChannelSigExplorer)生物电单信道可视化分析平台