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

如何用快慢指针优雅地找到链表的中间结点?——LeetCode 876 题详解


在这里插入图片描述

🔥个人主页:@月夜的风吹雨
🎥作者简介: C++研发方向学习者
📖学习专栏:《C语言》《VS2022编译器的使用》
🌄人生格言: 任何一个伟大的思想,都有一个微不足道的开始。

文章目录

    • 🔍 一、题目解析:我们到底要做什么?
      • ✅ 题目描述
      • ✅ 示例说明
        • 示例 1:
        • 示例 2:
    • 🧠 二、暴力解法:先遍历一遍求长度
    • 🚀 三、核心技巧:快慢指针法(Two Pointers)
    • 🧪 五、测试验证
    • 📊 六、性能对比
    • 🔄 七、拓展思考:你能想到其他变种吗?
    • 🎯 八、这篇文章能帮你什么?
    • 📣 九、欢迎你参与讨论!
    • 🧩 十、总结:记住这三点就够了!

🎯 掌握这一个经典技巧,轻松应对链表相关面试题!

如果你正在准备算法面试,或者想提升自己对数据结构的理解,那么链表绝对是绕不开的话题。今天我们要讲的是 LeetCode 上一道非常经典的题目:
在这里插入图片描述
在这里插入图片描述

876. 链表的中间结点(Middle of the Linked List)

别看它标着“简单”,但它的解法却蕴含着一种巧妙的思想——快慢指针(Two Pointers),这种思想在很多算法问题中都有广泛应用。

本文将带你从零开始理解这道题,并深入剖析其背后的逻辑与优化思路。读完这篇文章,你不仅能写出正确的代码,还能理解为什么这个方法是“最优”的。


🔍 一、题目解析:我们到底要做什么?

✅ 题目描述

给你单链表的头结点 head,请你找出并返回链表的中间结点

如果链表有两个中间结点,则返回第二个中间结点

✅ 示例说明

示例 1:
输入: [1,2,3,4,5]
输出: [3,4,5]
解释:链表只有一个中间结点,值为 3
示例 2:
输入: [1,2,3,4,5,6]
输出: [4,5,6]
解释:链表有两个中间结点(34),返回第二个(即 4)。

"💡 注意:这里返回的是结点本身,不是数值! "


🧠 二、暴力解法:先遍历一遍求长度

最直观的想法是:

  • 先遍历一次链表,计算出总长度 n
  • 再从头开始走 n / 2 + 1 步,到达中间结点。
/*** Definition for singly-linked list.* struct ListNode {*     int val;*     struct ListNode *next;* };*/
struct ListNode* middleNode(struct ListNode* head) {struct ListNode* ptail = head;int count = 0;   //记录节点总数while (ptail){ptail = ptail->next;count++;}count = count / 2 + 1;   //找到第几个节点while (count > 1){head = head->next;count--;}return head;}

⚠️ 缺点分析

  • 时间复杂度:O(n) + O(n/2) = O(n)
  • 空间复杂度:O(1)
  • 虽然效率尚可,但需要两次遍历,不够优雅。

“❌ 我们能不能只遍历一次就解决问题?”


🚀 三、核心技巧:快慢指针法(Two Pointers)

✅ 核心思想
让两个指针同时从头结点出发:

  • 快指针(fast) 每次走两步
  • 慢指针(slow) 每次走一步

当快指针走到末尾时,慢指针正好位于中间位置!

"🌟 这就是所谓的“龟兔赛跑”策略! "

🔁 为什么这样能行?
假设链表有 n 个结点:

  • 快指针每次走 2 步,慢指针每次走 1 步;
  • 当快指针走了 k 步时,慢指针走了 k/2 步;
  • 当快指针走到最后一个结点或 null 时,慢指针刚好走到第 (n+1)/2 个结点,也就是第二个中间结点。

⚠️当然这个还有一个坑,就是节点总数奇数偶数时又不一样
在这里插入图片描述
在这里插入图片描述

我们可以看出节点数为奇数时slow走到中间节点时fast刚好为最后一个节点,而为偶数时slow走到中间节点时fast却指向了NULL

✅ 完美满足题目要求!

✅ 四、代码实现(C语言)

struct ListNode* middleNode(struct ListNode* head) {struct ListNode* fast = head;struct ListNode* slow = head;while (fast && fast->next) {  //这里的fast和fast->next不能互换位置!!!slow = slow->next;fast = fast->next->next;}return slow;
}

📌 关键点解读

行号说明
fast && fast->next判断是否可以继续前进两步,避免空指针访问
fast = fast->next->next快指针跳两步
slow = slow->next慢指针走一步
返回 slow当快指针结束时,慢指针恰好在中间

🧪 五、测试验证

以示例 1 为例:[1,2,3,4,5]

步骤FASTSLOW
初始11
第1轮32
第2轮53
第3轮null3

✅ 结果正确:返回结点 3。

再看示例 2:[1,2,3,4,5,6]

步骤FASTSLOW
初始11
第1轮32
第2轮53
第3轮7(null)

✅ 返回结点 4,符合预期。


📊 六、性能对比

方法时间复杂度空间复杂度是否需要两次遍历
暴力法O(n)O(1)
快慢指针O(n)O(1)

虽然时间复杂度相同,但快慢指针只需一次遍历,更高效、更简洁,是真正的“优雅解法”。


🔄 七、拓展思考:你能想到其他变种吗?

🤔 变种 1:找倒数第 k 个结点
可以用类似双指针的方法:先让快指针走 k 步,然后一起走,直到快指针到末尾。

🤔 变种 2:判断链表是否有环
同样是快慢指针的经典应用!快指针追上慢指针则说明有环。

👉 推荐阅读:LeetCode 141. 环形链表 —— 使用快慢指针检测环的存在。

🤔 变种 3:删除链表的中间结点
可以在找到中间结点后,调整前驱节点的指针来删除。

🎯 八、这篇文章能帮你什么?

  • 学会一个实用的算法技巧:快慢指针不仅适用于本题,还广泛用于环检测、查找中位数等场景。
  • 提升代码质量:通过对比不同解法,理解“优雅”代码的设计思维。
  • 备战面试:链表类问题是大厂常考题,掌握这类模式能让你在面试中脱颖而出。
  • 建立系统性思维:从暴力解法 → 优化思路 → 拓展应用,培养完整的解题流程。

📣 九、欢迎你参与讨论!

如果你觉得这篇讲解对你有帮助,请不要吝啬你的支持👇:

✅ 点赞:让更多人看到这篇优质内容
💬 评论区留言:分享你在做这道题时遇到的坑,或者你有没有别的解法?
🔔 关注我:获取更多算法、数据结构、面试技巧干货!

"💌 你的每一次互动,都是对我最大的鼓励! "

🧩 十、总结:记住这三点就够了!

  • 快慢指针是解决链表问题的强大工具,尤其适合处理“距离”、“中点”、“环”等问题。
  • 不要只追求答案,更要理解背后的思想。比如为什么快指针走两步就能保证慢指针在中间?
  • 多练习、多思考、多总结。把每道题都当作一次思维训练的机会。

✅ 最后说一句

“编程的本质不是写代码,而是思考。”
—— 一位资深工程师的忠告

当你面对一道看似简单的题目时,不妨问自己:“有没有更聪明的做法?”也许,下一个突破点就在你的一次深思熟虑之中。


📌 下一期预告:我们将深入讲解「反转链表」的三种解法(迭代、递归、双指针),并探讨它们的时间空间复杂度差异。记得关注哦!


感谢阅读!
如果你喜欢这种风格的技术文章,欢迎转发、收藏、点赞,也欢迎在评论区告诉我你想看哪些话题~


在这里插入图片描述


文章转载自:

http://C1kbwiDx.xnrry.cn
http://zJDP9Xyt.xnrry.cn
http://6L14zTyR.xnrry.cn
http://wm8GzZ1p.xnrry.cn
http://RN6fgGaf.xnrry.cn
http://m8nJGI4g.xnrry.cn
http://J3WmC7Mq.xnrry.cn
http://6HE1A1IJ.xnrry.cn
http://UxpUxRmo.xnrry.cn
http://u7CYDj3R.xnrry.cn
http://djt3VGGo.xnrry.cn
http://l3kSYjJv.xnrry.cn
http://gMKwI56n.xnrry.cn
http://Y3A2RHV3.xnrry.cn
http://hNgsUBTq.xnrry.cn
http://BTMEAAlY.xnrry.cn
http://qZGPTp5X.xnrry.cn
http://o56NTmeg.xnrry.cn
http://zGURZDvW.xnrry.cn
http://CbfAC3CD.xnrry.cn
http://i7giA6fk.xnrry.cn
http://YWBNmu66.xnrry.cn
http://GCHItKfG.xnrry.cn
http://IQwb0fyy.xnrry.cn
http://BTYFqTnN.xnrry.cn
http://VPqJxHqk.xnrry.cn
http://uRZuJzaz.xnrry.cn
http://r7YU9Aw4.xnrry.cn
http://YA6mFIXf.xnrry.cn
http://XlbsXMQu.xnrry.cn
http://www.dtcms.com/a/387704.html

相关文章:

  • 计算机听觉分类分析:从音频信号处理到智能识别的完整技术实战
  • [torch] xor 分类问题训练
  • React学习教程,从入门到精通,React 表单完整语法知识点与使用方法(22)
  • ref、reactive和computed的用法
  • Redis哈希类型:高效存储与操作指南
  • MySQL 日志:undo log、redo log、binlog以及MVCC的介绍
  • 棉花、玉米、枸杞、瓜类作物分类提取
  • Python测试框架之pytest详解
  • qt QHPieModelMapper详解
  • MAC Typora 1.8.10无法打开多个md档
  • 零碳园区的 “追光者”:三轴光伏太阳花的技术创新与应用逻辑
  • MAC-Java枚举工具类实现
  • 「数据获取」全国村级点状矢量数据
  • Chromium 138 编译指南 macOS 篇:源代码获取(四)
  • 人工智能概念:NLP任务的评估指标(BLEU、ROUGE、PPL、BERTScore、RAGAS)
  • 机器学习基础:从线性回归到多分类实战
  • 深度学习基础:线性回归与 Softmax 回归全解析,从回归到分类的桥梁
  • Scikit-learn Python机器学习 - 分类算法 - 决策树
  • 【人工智能agent】--dify实现文找图、图找文、图找图
  • 基于 Landsat-8 数据的甘肃省金塔县主要农作物分类
  • 社区补丁的回复及常用链接
  • Pyside6 + QML - 信号与槽01 - Button 触发 Python 类方法
  • 视频理解学习笔记
  • Android Studio 将SVG资源转换成生成xml图
  • 后台管理系统详解:通用的系统架构介绍与说明
  • r-DMT市场报告:深度解析全球研究现状与未来发展趋势
  • 企业网络里的API安全防护指南
  • 了解学习DNS服务管理
  • Pycharm安装步骤
  • 分布式k8s集群管理是如何用karmada进行注册的?