Skip to content

Files

Latest commit

f2348f2 · May 23, 2022

History

History

0142.Linked List Cycle II

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
Apr 13, 2021
May 23, 2022
May 23, 2022
Jun 5, 2021
Jun 5, 2021
Jun 5, 2021
Dec 24, 2021
Feb 15, 2022
Dec 24, 2021

English Version

题目描述

给定一个链表的头节点  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
解释:链表中没有环。

 

提示:

  • 链表中节点的数目范围在范围 [0, 104]
  • -105 <= Node.val <= 105
  • pos 的值为 -1 或者链表中的一个有效索引

 

进阶:你是否可以使用 O(1) 空间解决此题?

解法

先利用快慢指针判断链表是否有环,没有环则直接返回 null

若链表有环,我们分析快慢相遇时走过的距离。

对于慢指针(每次走 1 步),走过的距离为 S=X+Y ①;快指针(每次走 2 步)走过的距离为 2S=X+Y+N(Y+Z) ②。如下图所示,其中 N 表示快指针与慢指针相遇时在环中所走过的圈数,而我们要求的环入口,也即是 X 的距离:

我们根据式子 ①②,得出 X+Y=N(Y+Z) => X=(N-1)(Y+Z)+Z

N=1(快指针在环中走了一圈与慢指针相遇) 时,X=(1-1)(Y+Z)+Z,即 X=Z。此时只要定义一个 p 指针指向头节点,然后慢指针与 p 开始同时走,当慢指针与 p 相遇时,也就到达了环入口,直接返回 p 即可。

N>1时,也是同样的,说明慢指针除了走 Z 步,还需要绕 N-1 圈才能与 p 相遇。

Python3

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def detectCycle(self, head: ListNode) -> ListNode:
        slow = fast = head
        has_cycle = False
        while not has_cycle and fast and fast.next:
            slow, fast = slow.next, fast.next.next
            has_cycle = slow == fast
        if not has_cycle:
            return None
        p = head
        while p != slow:
            p, slow = p.next, slow.next
        return p

Java

/**
 * 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) {
        ListNode slow = head, fast = head;
        boolean hasCycle = false;
        while (!hasCycle && fast != null && fast.next != null) {
            slow = slow.next;
            fast = fast.next.next;
            hasCycle = slow == fast;
        }
        if (!hasCycle) {
            return null;
        }
        ListNode p = head;
        while (p != slow) {
            p = p.next;
            slow = slow.next;
        }
        return p;
    }
}

TypeScript

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     val: number
 *     next: ListNode | null
 *     constructor(val?: number, next?: ListNode | null) {
 *         this.val = (val===undefined ? 0 : val)
 *         this.next = (next===undefined ? null : next)
 *     }
 * }
 */

function detectCycle(head: ListNode | null): ListNode | null {
    let slow = head,
        fast = head;
    while (fast) {
        slow = slow.next;
        if (!fast.next) return null;
        fast = fast.next.next;

        if (fast == slow) {
            let cur = head;
            while (cur != slow) {
                slow = slow.next;
                cur = cur.next;
            }
            return cur;
        }
    }
    return null;
}

C++

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        ListNode* slow = head;
        ListNode* fast = head;
        bool hasCycle = false;
        while (!hasCycle && fast && fast->next) {
            slow = slow->next;
            fast = fast->next->next;
            hasCycle = slow == fast;
        }
        if (!hasCycle) {
            return nullptr;
        }
        ListNode* p = head;
        while (p != slow) {
            p = p->next;
            slow = slow->next;
        }
        return p;
    }
};

JavaScript

/**
 * Definition for singly-linked list.
 * function ListNode(val) {
 *     this.val = val;
 *     this.next = null;
 * }
 */

/**
 * @param {ListNode} head
 * @return {ListNode}
 */
var detectCycle = function (head) {
    let slow = head;
    let fast = head;
    let hasCycle = false;
    while (!hasCycle && fast && fast.next) {
        slow = slow.next;
        fast = fast.next.next;
        hasCycle = slow == fast;
    }
    if (!hasCycle) {
        return null;
    }
    let p = head;
    while (p != slow) {
        p = p.next;
        slow = slow.next;
    }
    return p;
};

Go

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func detectCycle(head *ListNode) *ListNode {
    slow, fast := head, head
    hasCycle := false
    for !hasCycle && fast != nil && fast.Next != nil {
        slow, fast = slow.Next, fast.Next.Next
        hasCycle = slow == fast
    }
    if !hasCycle {
        return nil
    }
    p := head
    for p != slow {
        p, slow = p.Next, slow.Next
    }
    return p
}

...