142_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.

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

/**
 * 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) {
        
    }
};

题目解释:给定一个链表,如果有环,返回环开始的结点,如果没有,则返回null

要求: 不适用额外的空间

思路:
  1. 使用快慢指针(快指针2倍速)确认该链表是否有环, 如果有环,则两指针会相遇,设相遇于Z点;同141_Linked List Cycle

  2. 假设链表的起始位置为X, 环的起始位置为Y, 有环时快慢指针相遇于Z点;Lxy = a; Lyz = b, Lzy = c;

  3. 相遇于Z点, 慢指针 走了 a+b的长度, 快指针走了2*(a+b)长度,假设相遇时,快指针已经走了N圈的环长度,b+c是环的长度;那么快指针 也相当于走了a+b+n*(b+c) (解释下:a+b 确保指针走在Z处,Z处是环内的位置,最终相遇在Z处,也就是快指针多走了N圈的环长度)

    即: 2*(a+b) = a+b+N*(b+c) => a+b = N*(b+c) => a = (N-1)b+Nc
    => a = (N-1)(b+c) + c (Z点 开始 走个c长度到Y点,然后走整数倍的圈数,还是Y点,可以再用快慢指针求解Y点位置)

  4. 有了这个关系,那么 一个指针在X点,一个指针在Z点,以相同的速度走,当它们相遇的时候,相遇的位置恰好就是Y点,也就是环开始的位置;

在这里插入图片描述

算法是这样的

1.快慢指针,找到第一次相遇的点
2.接着慢指针回归起始位置,快指针调整和慢指针一个速度,再次相遇的位置就是环开始的位置

参考牛客网看到的wangxiaobao对此题的回答,链接如下:
https://www.nowcoder.com/questionTerminal/6e630519bf86480296d0f1c868d425ad

代码如下:

/**
 * 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) {
        if (nullptr == head)
			return nullptr;
		ListNode *fast = head;

		ListNode *slow = head;

		while (nullptr != fast->next && nullptr != fast->next->next && nullptr != slow->next)
		{
			fast = fast->next->next;
			slow = slow->next;
			if (slow == fast)
			{
				slow = head;
				// 已经确认有环,就可以不用判断next是否为空了
				while (slow != fast)
				{
					slow = slow->next;
					fast = fast->next;
				}
				return fast; //或者return slow
			}
		}
		return nullptr;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值