leetcode --- Linked List Cycle [Floyd's cycle-finding algorithm]

Linked List Cycle

Given a linked list, determine if it has a cycle in it.

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

Linked List Two Pointers

‘‘‘
Created on Nov 13, 2014

@author: ScottGu<[email protected], [email protected]>
‘‘‘
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    # @param head, a ListNode
    # @return a boolean
    def hasCycle(self, head):
        node=head
        visited={}
        while(node!=None):
            if(visited.has_key(node)):
                return True
            visited[node]=1
            node=node.next
        return False

如果只是解题的话非常简单,有趣的地方在于Follow up,而Follow up最常见的解法是使用两个walker,二者速度不同,当二者碰面则为有环,遇到None则为无环。

但是问题来了,二者速度不同的话在环中一定会相遇吗?如何数学证明?

佛洛依德龟兔算法

这个猜想其实早就被证明了,wikihttp://en.wikipedia.org/wiki/Cycle_detection#Tortoise_and_hare ,so有更详细的解释:

Let me try to clarify the cycle detection algorithm that is provided at http://en.wikipedia.org/wiki/Cycle_detection#Tortoise_and_hare in my own words.

I refer to the figure  in my explanation.

How it works

Let‘s have a tortoise and a hare (name of the pointers) pointing to the beginning of the list with a cycle.

Let‘s hypothesize that if we move tortoise 1 step at a time, and hare 2 steps at a time, they will eventually meet at a point. Let‘s show that first of all this hypothesis is true.

The figure illustrates a list with a cycle. The cycle has a length of n and we are initially m steps away from the cycle. Also let‘s say that the meeting point is k steps away from the cycle beginning and tortoise and hare meets after a total of i steps.

The following 2 conditions must hold:

1) i = m + p * n + k

2) 2i = m + q * n + k

The first one says that tortoise moves i steps and in these i steps it first gets to the cycle. Then it goes through the cycle p times for some positive number p. Finally it goes over k more nodes until it meets hare.

A similar is true for hare. It moves 2i steps and in these 2i steps it first gets to the cycle. Then it goes through the cycle q times for some positive number q. Finally it goes over k more nodes until it meets tortoise.

Therefore,

2 ( m + p * n + k ) = m + q * n + k

=> 2m + 2pn + 2k = m + nq + k

=> m + k = ( q - 2p ) n

Among m, n, k, p, q, the first two are properties of the given list. If we can show that there is at least one set of values for k, q, p that makes this equation true we show that the hypothesis is correct.

One such solution set is as follows:

p = 0

q = m

k = m n - m

We can verify that these values work as follows:

m + k = ( q - 2p ) n

=> m + mn - m = ( m - 2*0) n

=> mn = mn.

For this set, i is

i = m + p n + k

=> m + 0 * n + mn - m = mn.

Of course, you should see that this is not necessarily the smallest i possible. In other words, tortoise and hare might have already met before many times. However, since we show that they meet at some point at least once we can say that the hypothesis is correct. So they would have to meet if we move one of them 1 step, and the other one 2 steps at a time.

Now we can go to the second part of the algorithm which is how to find the beginning of the cycle.

Cycle Beginning

Once tortoise and hare meet, let‘s put tortoise back to the beginning of the list and keep hare where they met (which is k steps away from the cycle beginning).

The hypothesis is that if we let them move at the same speed (1 step for both), the first time they ever meet again will be the cycle beginning.

Let‘s prove this hypothesis.

Let‘s first assume some oracle tells us what m is.

Then, if we let them move m + k steps, tortoise would have to arrive at the point they met originally (k steps away from the cycle beginning - see in the figure).

Previously we showed that m + k = (q - 2p) n.

Since m + k steps is a multiple of cycle length n, hare, in the mean time, would go through the cycle (q-2p) times and would come back to the same point (k steps away from the cycle beginning).

Now, instead of letting them move m + k steps, if we let them move only m steps, tortoise would arrive at the cycle beginning. Hare would go be k steps short of completing (q-2p) rotations. Since it started k steps in front of the cycle beginning, hare would have to arrive at the cycle beginning.

As a result, this explains that they would have to meet at the cycle beginning after some number of steps for the very first time (very first time because tortoise just arrived at the cycle after m steps and it could never see hare which was already in the cycle).

Now we know that the number of steps we need to move them until they meet turns out to be the distance from the beginning of the list to the cycle beginning, m. Of course, the algorithm does not need to know what m is. It will just move both tortoise and hare one step at a time until they meet. The meeting point has to be the cycle start and the number of steps must be the distance (m) to the cycle beginning. Assuming we know the length of the list, we can also, compute the length of the cycle of subtracting m from the list length.

leetcode --- Linked List Cycle [Floyd's cycle-finding algorithm]

时间: 2024-10-04 12:06:47

leetcode --- Linked List Cycle [Floyd's cycle-finding algorithm]的相关文章

LeetCode Linked List Cycle II

/** * 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* fast = head; ListNode* slow = head;

LeetCode: Linked List Cycle [141]

[题目] Given a linked list, determine if it has a cycle in it. Follow up: Can you solve it without using extra space? [题意] 判断一个单向链表是否有环 [思路] 维护两个指针p1和p2,p1每次向前移动一步,p2每次向前移动两步 如果p2能够追上p1,则说明链表中存在环 [代码] /** * Definition for singly-linked list. * struct L

LeetCode: Linked List Cycle II [142]

[题目] Given a linked list, return the node where the cycle begins. If there is no cycle, return null. Follow up: Can you solve it without using extra space? [题意] 给定一个单向链表,如果链表有环,则返回环开始的位置. [思路] 仍然是维护两个指针, p1, p2, p1每次走一步, p2每次走两步 假设进入环之前要走X步,环长为y步,p2第

Leetcode:Linked List Cycle 链表是否存在环

Linked List Cycle: Given a linked list, determine if it has a cycle in it. Follow up:Can you solve it without using extra space? 解题分析: 大致思想就是设置两个指针,一个指针每次走两步,一个指针每次走一步,如果这两个指针碰头了,那么一定就存在环 可以类比两个人在环形操场跑步,同时出发,一个跑得快,一个跑得慢,如果跑得快的人追上跑得慢的人,那么跑得快的人相当于多跑了一整

LeetCode[Linked List]: Linked List Cycle II

Given a linked list, return the node where the cycle begins. If there is no cycle, return null. Follow up: Can you solve it without using extra space? 这个题目跟Linked List Cycle一样,我也没有能够自己独立找到解决方法,而是借助Discuss学到了一个非常巧妙的解决方法: 首先借助LeetCode[Linked List]: Lin

[LeetCode]Linked List Cycle II解法学习

问题描述如下: Given a linked list, return the node where the cycle begins. If there is no cycle, return null. Follow up: Can you solve it without using extra space? 从问题来看,如果可以充分利用额外空间的话,这个题目是不难的,然而题目提出了一个要求,能否在不使用任何额外空间的情况下解决这个问题. 通过反复思考,我觉得这题类似于追击问题,可以用一个

HDU 4889 Scary Path Finding Algorithm

题意: 构造一幅图  使题中给出的程序按该图执行  最终变量doge大于输入的C跳出 思路: 出题人思维简直神了!  实在是膜拜!  借题解的图: 按照图中所画  可以继续向右延伸 为何这样可以??  为何边权要这么取?? 先回答第二个问题: 取负数是为了可以不断的去更新  例如如果走了上面的-4那条边  那么它右边的所有点就又可以再更新一次  这样使更新达到了指数级别 (其实可以把所有的值加上一个值K  不过这个K一定要取好!) 除了负数外我们发现数字都是2的几次幂  如果我们按2进制来考虑的

[LeetCode]Linked List Cycle

题目:Linked List Cycle 判断一个单链表中是否有环,要求常量空间复杂度: 思路: 使用两个指针同时从链表表头开始移动,一个移动一步,一个移动两步,直到两个指针重合或某一指针指向链尾. 两个指针重合则单链表有环存在,否则没有. 第二个指针以第一个指针的两倍的速度移动,而第一个指针每次移动一步,这样只要有环,两个指针必定能重合. bool LeetCode::hasCycle(ListNode *head){ if (!head)return false; ListNode *p =

LeetCode: Linked List Cycle ii 解题报告

Linked List Cycle ii Given a linked list, return the node where the cycle begins. If there is no cycle, return null. Follow up: Can you solve it without using extra space? SOLUTION 1: 最开始的想法和 Linked List Cycle这一题一样. SOLUTION 2: 同样是两个指针,一快一慢,相遇时跳出循环,只