判断链表是否环形

本文为作者原创,转载请注明出处:https://www.cnblogs.com/zhaoqingqing/p/11853924.html



问题描述#

怎么能够更高效地判断一个链表是否有环呀?

首先创建两个指针p1和p2(在Java里就是两个对象引用),让它们同时指向这个链表的头节点。

然后开始一个大循环,在循环体中,让指针p1每次向后移动1个节点,让指针p2每次向后移动2个节点,然后比较两个指针指向的节点是否相同。如果相同,则可以判断出链表有环,如果不同,则继续下一次循环

示意图

学过小学奥数的读者,一定听说过数学上的追及问题。

此方法就类似于一个追及问题。在一个环形跑道上,两个运动员从同一地点起跑,一个运动员速度快,另一个运动员速度慢。当两人跑了一段时间后,速度快的运动员必然会再次追上并超过速度慢的运动员,原因很简单,因为跑道是环形的。

假设链表的节点数量为n,则该算法的时间复杂度为O(n)。

除两个指针外,没有使用任何额外的存储空间,所以空间复杂度是O(1)

示例代码#

Copy
public class LinkedListCycle { /** * 判断是否有环 * @param head 链表头节点 */ public static boolean isCycle(Node head) { Node p1 = head; Node p2 = head; while (p2!=null && p2.next!=null){ p1 = p1.next; p2 = p2.next.next; if(p1 == p2){ return true; } } return false; } /** * 链表节点 */ private static class Node { int data; Node next; Node(int data) { this.data = data; } } public static void main(String[] args) throws Exception { Node node1 = new Node(5); Node node2 = new Node(3); Node node3 = new Node(7); Node node4 = new Node(2); Node node5 = new Node(6); node1.next = node2; node2.next = node3; node3.next = node4; node4.next = node5; node5.next = node2; System.out.println(isCycle(node1)); } }

扩展#

如果链表有环,如何求出环的长?

当两个指针首次相遇,证明链表有环的时候,让两个指针从相遇点继续循环前进,并统计前进的循环次数,直到两个指针第2次相遇。此时,统计出来的前进次数就是环长。

因为指针p1每次走1步,指针p2每次走2步,两者的速度差是1步。当两个指针再次相遇时,p2比p1多走了整整1圈因此,环长 = 每一次速度差 × 前进次数 = 前进次

作者:赵青青   一名在【网易游戏】做游戏开发的程序员,擅长Unity3D,游戏开发,.NET等领域。
本文版权归作者和博客园共有,欢迎转载,转载之后请务必在文章明显位置标出原文链接和作者,谢谢。
如果本文对您有帮助,请点击【推荐】您的赞赏将鼓励我继续创作!想跟我一起进步么?那就【关注】我吧。
posted @   赵青青  阅读(1524)  评论(0编辑  收藏  举报
编辑推荐:
· .NET Core 托管堆内存泄露/CPU异常的常见思路
· PostgreSQL 和 SQL Server 在统计信息维护中的关键差异
· C++代码改造为UTF-8编码问题的总结
· DeepSeek 解答了困扰我五年的技术问题
· 为什么说在企业级应用开发中,后端往往是效率杀手?
阅读排行:
· 10亿数据,如何做迁移?
· 推荐几款开源且免费的 .NET MAUI 组件库
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 易语言 —— 开山篇
· Trae初体验
CONTENTS
点击右上角即可分享
微信分享提示