首页 > 其他分享 >环形链表

环形链表

时间:2023-04-03 22:01:20浏览次数:34  
标签:head slow 环形 fast pos 链表 指针

给定一个链表的头节点  head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。

不允许修改 链表。

示例 1:

 

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

输出:返回索引为 1 的链表节点解释:链表中有一个环,其尾部连接到第二个节点。

示例 2:

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

输出:返回索引为 0 的链表节点

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

 

输入:head = [1], pos = -1

输出:返回 null

解释:链表中没有环。

哈希表

public class Solution {
    public ListNode detectCycle(ListNode head) {
        ListNode pos = head;
        Set<ListNode> visited = new HashSet<ListNode>();
        while (pos != null) {
            if (visited.contains(pos)) {
                return pos;
            } else {
                visited.add(pos);
            }
            pos = pos.next;
        }
        return null;
    }
}

时间复杂度: O(N),其中 N 为链表中节点的数目。我们恰好需要访问链表中的每一个节点。

空间复杂度: O(N),其中 N 为链表中节点的数目。我们需要将链表中的每个节点都保存在哈希表当中。 

快慢指针

我们使用两个指针, fast与 slow。它们起始都位于链表的头部。随后,slow 指针每次向后移动一个位置,而fast 指针向后移动两个位置。如果链表中存在环,则 fast指针最终将再次与 slow指针在环中相遇。 如下图所示,设链表中环外部分的长度为a。 slow指针进入环后,又走了b 的距离与 fast相遇。此时,fast指针已经走完了环的n 圈,因此它走过的总距离为a+n(b+c)+b=a+(n+1)b+nc。

 

根据题意,任意时刻,fast 指针走过的距离都为slow 指针的 2 2 倍。因此,我们有a+(n+1)b+nc=2(a+b)⟹a=c+(n−1)(b+c) 有了 a=c+(n−1)(b+c) 的等量关系,我们会发现:从相遇点到入环点的距离加上n−1 圈的环长,恰好等于从链表头部到入环点的距离。 因此,当发现slow与fast相遇时,我们再额外使用一个指针ptr。起始,它指向链表头部;随后,它和slow 每次向后移动一个位置。最终,它们会在入环点相遇。

public class Solution {
    public ListNode detectCycle(ListNode head) {
        if (head == null) {
            return null;
        }
        ListNode slow = head, fast = head;
        while (fast != null) {
            slow = slow.next;
            if (fast.next != null) {
                fast = fast.next.next;
            } else {
                return null;
            }
            if (fast == slow) {
                ListNode ptr = head;
                while (ptr != slow) {
                    ptr = ptr.next;
                    slow = slow.next;
                }
                return ptr;
            }
        }
        return null;
    }
}

时间复杂度:O(N),其中 N 为链表中节点的数目。在最初判断快慢指针是否相遇时,slow 指针走过的距离不会超过链表的总长度;随后寻找入环点时,走过的距离也不会超过链表的总长度。因此,总的执行时间为O(N)+O(N)=O(N)。

空间复杂度:O(1)。我们只使用了 slow , fast , ptr三个指针。 

标签:head,slow,环形,fast,pos,链表,指针
From: https://www.cnblogs.com/zhengbiyu/p/17284602.html

相关文章

  • 带环的单链表追击之拓展证明
    对于单链表有环问题,上一期,我们已经详细讲解了!!而快慢指针功不可没!!对于本期我们再次回顾,链表有环问题时,不难心中存在一个疑问,一定能追得上吗?会不会错过??那么为什么??为何能追上,什么情况下会追不上!!这就是我们今天讨论的重点!!假设单链表有环,快指针每次走两步,而慢指针每次走一步!!那么,快慢指......
  • 23. 合并 K 个升序链表
    题目描述给你一个链表数组,每个链表都已经按升序排列。请你将所有链表合并到一个升序链表中,返回合并后的链表。解题1/**2*Definitionforsingly-linkedlist.3*publicclassListNode{4*intval;5*ListNodenext;6*ListNo......
  • 114.二叉树展开为链表 Java
    114.二叉树展开为链表给你二叉树的根结点root,请你将它展开为一个单链表:展开后的单链表应该同样使用TreeNode,其中right子指针指向链表中下一个结点,而左子指针始终为null。展开后的单链表应该与二叉树先序遍历顺序相同。示例1:输入:root=[1,2,5,3,4,null,6]输出......
  • 力扣---剑指 Offer 36. 二叉搜索树与双向链表
    输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的循环双向链表。要求不能创建任何新的节点,只能调整树中节点指针的指向。 为了让您更好地理解问题,以下面的二叉搜索树为例:   我们希望将这个二叉搜索树转化为双向循环链表。链表中的每个节点都有一个前驱和后继指针。对......
  • 160. 相交链表
    160.相交链表给你两个单链表的头节点 headA和headB,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回null。图示两个链表在节点c1开始相交:题目数据保证整个链式结构中不存在环。注意,函数返回结果后,链表必须保持其原始结构。自定义评测:......
  • 876. 链表的中间结点
    876.链表的中间结点给你单链表的头结点head,请你找出并返回链表的中间结点。如果有两个中间结点,则返回第二个中间结点。示例1:输入:head=[1,2,3,4,5]输出:[3,4,5]解释:链表只有一个中间结点,值为3。示例2:输入:head=[1,2,3,4,5,6]输出:[4,5,6]解释:该链表有两个......
  • 23. 合并 K 个升序链表
    23.合并K个升序链表给你一个链表数组,每个链表都已经按升序排列。请你将所有链表合并到一个升序链表中,返回合并后的链表。示例1:输入:lists=[[1,4,5],[1,3,4],[2,6]]输出:[1,1,2,3,4,4,5,6]解释:链表数组如下:[1->4->5,1->3->4,2->6]将它们合并到一个有序链......
  • 链表完成多项式乘法
    多项式乘法是在多项式加法的基础上完成的。1、多项式加法1#include<iostream>2usingnamespacestd;3typedefstructlnode{4intcoef;5intexp;6lnode*next;7}lnode;8classpoly{9lnode*head;10public:11voidcreate(in......
  • 21. 合并两个有序链表
     21. 合并两个有序链表做法1:构建虚拟头节点,而后双指针做法。/***Definitionforsingly-linkedlist.*structListNode{*intval;*ListNode*next;*ListNode():val(0),next(nullptr){}*ListNode(intx):val(x),next(nullptr){}......
  • leetcode876. 链表的中间结点
      876. 链表的中间结点方法一:最简单的做法,先求出整个链表的长度,再求1/2处节点的位置。/***Definitionforsingly-linkedlist.*structListNode{*intval;*ListNode*next;*ListNode():val(0),next(nullptr){}*ListNode(intx)......