LeetCode题解—链表中环的检测

简介: 今天说链表算法题的最后一题:环的检测

前言


今天说链表算法题的最后一题:环的检测



题目:链表中环的检测


给定一个链表,判断链表中是否有环


如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 pos为环的起点位置。


如果链表中存在环,则返回 true 。否则,返回 false 。


进阶:你能用 O(1)(即,常量)内存解决此问题吗?


示例 1:


8.png


输入:head = [3,2,0,-4], pos = 1

输出:true

解释:链表中有一个环,其尾部连接到第二个节点。


示例 2:输入:head = [1,2], pos = 0

输出:true

解释:链表中有一个环,其尾部连接到第一个节点。


示例 3:输入:head = [1], pos = -1

输出:false

解释:链表中没有环。


解法一


题目比较长,意思其实很简单,就是同一个结点会不会被两个不同结点所连接,反应到链表就是:


是否有两个结点的next都指向同一个结点,如果有,那就代表链表中有环型结构。


所以我们遍历链表,然后将链表的每个结点存储起来,如果发现有重复就代表有环:


public class Solution {
    public boolean hasCycle(ListNode head) {
        Set<ListNode> nodeSet = new HashSet<ListNode>();
        while (head != null) {
            if (!nodeSet.add(head)) {
                return true;
            }
            head = head.next;
        }
        return false;
    }
}


时间复杂度


时间复杂度为O(n)


空间复杂度


空间复杂度为O(n)


解法二


题目有提示,是否可以有空间复杂度为O(1)的解法呢?


快慢指针,没错,又是快慢指针


快指针每次走两步,慢指针每次走一步,正常情况下,没有环的话,两者是不会相遇的。


如果有环结构,那么在环里面,如果快慢指针之间的距离为X,那么每走一步,快指针和慢指针之间的距离都会-1,所以总会有一个时刻,他们会相遇。


所以只要发现有相遇的情况,就证明该链表有环


这种算法也叫做龟兔赛跑算法


public class Solution {
    public boolean hasCycle(ListNode head) {
        if (head == null || head.next == null) {
            return false;
        }
        ListNode slow = head;
        ListNode fast = head;
        while(fast != null && fast.next != null) {
            fast = fast.next.next;
            slow = slow.next;
            if(fast == slow){
                return true; 
            }
        }
        return false;
    }
}


其实关于龟兔赛跑算法还有很多问法,比如如何确认环的起点,如何确认环的长度等等,下次再详细聊聊。


时间复杂度


时间复杂度为O(n)


空间复杂度


只用两个额外的指针,所以空间复杂度为O(1)


参考


https://leetcode-cn.com/problems/linked-list-cycle/

目录
相关文章
|
15天前
|
索引 Python
【Leetcode刷题Python】328. 奇偶链表
在不使用额外空间的情况下,将链表中的奇数和偶数索引节点重新排序的方法,并提供了相应的Python实现代码。
22 0
|
15天前
|
Python
【Leetcode刷题Python】25.K 个一组翻转链表
解决LeetCode "K 个一组翻转链表" 问题的三种方法:使用栈、尾插法和虚拟节点顺序法,并提供了每种方法的Python实现代码。
23 0
|
4天前
|
算法
LeetCode第24题两两交换链表中的节点
这篇文章介绍了LeetCode第24题"两两交换链表中的节点"的解题方法,通过使用虚拟节点和前驱节点技巧,实现了链表中相邻节点的交换。
LeetCode第24题两两交换链表中的节点
|
4天前
|
存储 算法
LeetCode第86题分隔链表
文章介绍了LeetCode第86题"分隔链表"的解法,通过创建两个新链表分别存储小于和大于等于给定值x的节点,然后合并这两个链表来解决问题,提供了一种简单易懂且操作原链表的解决方案。
LeetCode第86题分隔链表
|
4天前
|
存储 算法
LeetCode第83题删除排序链表中的重复元素
文章介绍了LeetCode第83题"删除排序链表中的重复元素"的解法,使用双指针技术在原链表上原地删除重复元素,提供了一种时间和空间效率都较高的解决方案。
LeetCode第83题删除排序链表中的重复元素
|
4天前
|
算法
LeetCode第23题合并 K 个升序链表
这篇文章介绍了LeetCode第23题"合并K个升序链表"的解题方法,使用分而治之的思想,通过递归合并链表的方式解决了这个难题。
LeetCode第23题合并 K 个升序链表
|
14天前
|
Python
【Leetcode刷题Python】114. 二叉树展开为链表
LeetCode上114号问题"二叉树展开为链表"的Python实现,通过先序遍历二叉树并调整节点的左右指针,将二叉树转换为先序遍历顺序的单链表。
15 3
【Leetcode刷题Python】114. 二叉树展开为链表
|
4天前
|
算法
LeetCode第92题反转链表 II
文章分享了LeetCode第92题"反转链表 II"的解法,通过使用四个指针来记录和更新反转链表段的头部、尾部以及前一个和后一个节点,提供了一种清晰且易于理解的解决方案。
LeetCode第92题反转链表 II
|
4天前
|
算法
LeetCode第21题合并两个有序链表
该文章介绍了 LeetCode 第 21 题合并两个有序链表的解法,通过创建新链表,依次比较两个链表的头节点值,将较小的值插入新链表,直至其中一个链表遍历完,再将另一个链表剩余部分接到新链表后面,实现合并。
LeetCode第21题合并两个有序链表
|
4天前
|
算法
LeetCode第19题删除链表的倒数第 N 个结点
该文章介绍了 LeetCode 第 19 题删除链表的倒数第 N 个结点的解法,通过使用快慢双指针,先将快指针移动 n 步,然后快慢指针一起遍历,直到快指针到达链尾,从而找到倒数第 N 个结点的前一个结点进行删除,同时总结了快慢指针可减少链表遍历次数的特点。
LeetCode第19题删除链表的倒数第 N 个结点