【Leetcode 142】Linked List Cycle Ⅱ - MEDIUM

Leetcode 142 Linked List Cycle Ⅱ - MEDIUM

题目

Given a linked list, return the node where the cycle begins. If there is no cycle, return null.
.
To represent a cycle in the given linked list, we use an integer pos which represents the position (0-indexed) in the linked list where tail connects to. If pos is -1, then there is no cycle in the linked list.
.
Note: Do not modify the linked list.

给定一个链表,返回环开始的结点。如果没有环,则返回null.

样例输入输出

为了表示给定的链表中的环,我们用整数pos来代表链表中尾结点连接到的位置。如果pos值为-1,则代表链表中没有循环。


样例1:
输入:head = [3,2,0,-4],pos = 1
(表示一个含有3、2、0、-4四个结点的链表,且尾结点-4指向位置为1的结点2)
输出:1
(表示环开始的结点是位置为1的结点)

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

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


思路

基于141题【Leetcode 141】Linked List Cycle - EASY的使用HashSet的思路,
这里仍然可以使用HashSet。

题解

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public ListNode detectCycle(ListNode head) {
        HashSet nodesVisited = new HashSet();
        while(head!=null){
            if(nodesVisited.contains(head)){
                return head;
            }
            else{
                nodesVisited.add(head);
                head=head.next;
            }
        }
        return null;
    }
}

在这里插入图片描述

反思

复杂度分析

时间复杂度:O(n).
空间复杂度:O(n).

思路反思

由于该题是141题的升级,我们可以考虑能否使用141题使用的快慢指针的方法,将空间复杂度降至O(1)。

扩展学习

我们尝试使用快慢指针的方式,先来分析以下这张图:
在这里插入图片描述
我们可以得知,链表长度为a+b+c,环的长度为b+c。
快指针fp从头结点开始,以2结点/次的速率移动;
慢指针sp从头结点开始,以1结点/次的速率移动。

当快慢结点在C点首次相遇时,sp一定还没走完环的一圈,而fp已经在环内走了n圈(n≥1).

Lfp = (a + b) + n (b + c) (n ≥ 1)
Lsp= a + b
.
又因为Lfp = 2Lsp
有 2(a + b) = (a + b) + n (b + c)
得到 a = c + (n - 1)(b + c) (n ≥ 1)

我们得到的式子a = c + (n - 1)(b + c)(n ≥ 1)有什么具体含义呢?
意思是a的长度比c的长度多出的是环长的整数倍(可能为0)。

于是,此时我们将快指针fp指向头结点A,速率改为1结点/次。
然后让fp和sp同时移动。
那么如果二者相遇,一定是在环上,有Lfp ≥ a。
而当fp到达B点时,刚好Lsp=Lfp = a = c + (n - 1)(b + c)(n ≥ 1),则sp也刚好到达B点。即两者再次相遇的点就是环开始的点。

代码如下:

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public ListNode detectCycle(ListNode head) {
        if(head==null || head.next == null){
            return null;
        }
        ListNode fast = head;
        ListNode slow = head;
        while(fast != null && fast.next != null){
            fast = fast.next.next;
            slow = slow.next;
            if(fast == slow){
                break;    
            }
        }
        if(fast == null || fast.next == null){
            return null;
        }
        fast = head;
        while(fast!=slow){
            fast = fast.next;
            slow = slow.next;
        }
        return fast;
    }
}

在这里插入图片描述
时间复杂度为O(n).
空间复杂度为O(1).

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值