142. Linked List Cycle II**

142. Linked List Cycle II**

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

题目描述

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.

Example 1:

Input: head = [3,2,0,-4], pos = 1
Output: tail connects to node index 1
Explanation: There is a cycle in the linked list, where tail connects to the second node.

Example 2:

Input: head = [1,2], pos = 0
Output: tail connects to node index 0
Explanation: There is a cycle in the linked list, where tail connects to the first node.

Example 3:

Input: head = [1], pos = -1
Output: no cycle
Explanation: There is no cycle in the linked list.

Follow-up:
Can you solve it without using extra space?

C++ 实现 1

  • 双指针方法/快慢指针

链表问题中的一个重要的方法叫双指针法。定义两个指针,一个叫慢指针,另一个叫快指针。通常慢指针每次向前移动一个节点,而快指针每次向前移动若干个节点。这个方法通常用于寻找链表中特定的位置。比如找到链表的中点,可以让快指针每次移动两个节点。这样当快指针到达链表末尾时,慢指针刚好在链表中间的位置。

假设环的起点就是 n2 (这部分内容参考 Linked List Cycle II)

        n6-----------n5
        |            |
  n1--- n2---n3--- n4|

我们仍然可以使用两个指针fastslowfast走两步,slow走一步,判断是否有环,当有环重合之后,譬如上面在 n5 重合了,那么如何得到 n2 呢?

首先我们知道,fast 每次比 slow 多走一步,所以重合的时候,fast 移动的距离是 slow 的两倍,我们假设 n1n2 距离为 a ,n2n5 距离为 b,n5n2 距离为c,fast 走动距离为 a + b + c + b,而 slow 为a + b,有方程 a + b + c + b = 2 x (a + b),可以知道 a = c,所以我们只需要在重合之后,一个指针从 n1,而另一个指针从 n5,都每次走一步,那么就可以在 n2 重合了。

另外需要注意的是, 在 141. Linked List Cycle* 解答中, 我初始化 fastslow 不在同一个节点, 在判断是否存在环时是可以这样用的, 其实就相当于, fastslow 节点从某个虚拟节点出发, 前者提前走了两步, 而后者走了一步.

但此题中, 最后将 fastslow 初始化为 head, 即同时在起始节点, 只有这样操作, 最后才能达到重合时 fast 走的距离是 slow 走的距离的两倍.

class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        auto slow = head, fast = head;
        // 首先判断是否存在环
        while (fast && fast->next) {
            slow = slow->next;
            fast = fast->next->next;
            // 如果存在环, 那么开始找环
            if (slow == fast) {
                slow = head;
                while (slow != fast) {
                    slow = slow->next;
                    fast = fast->next;
                }
                return slow;
            }
        }
        return nullptr;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值