Linked List Cycle I

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

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

该问题是经典面试问题,其标准解法是用两个指针,一快一慢,如果在快的指针能够追上慢的指针,则有环,否则无环。为了熟悉一下Python,用Python又写了一遍。

/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
bool hasCycle(ListNode *head) {
if(head==NULL||head->next==NULL)
return false;
ListNode *flag1=head;
ListNode *flag2=head;
while()
{
if(flag1->next==NULL)
return false;
else
flag1=flag1->next;
if(flag2->next==NULL)
return false;
else
flag2=flag2->next;
if(flag2->next==NULL)
return false;
else
flag2=flag2->next;
if(flag1==flag2)
return true; }
}
};

Python版本:

# 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):
if head==None or head.next==None:
return False
flag1=head
flag2=head
while True:
flag1=flag1.next
if flag1.next==None:
return False
flag2=flag2.next
if flag2.next==None:
return False
flag2=flag2.next
if flag2.next==None:
return False
if flag1==flag2:
return True

 Linked List Cycle II

Given a linked list, return the node where the cycle begins. If there is no cycle, return null.

Note: Do not modify the linked list.

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

感觉又是一道数学题,没想了,直接看的人家是怎么做的。

转自:http://www.cnblogs.com/x1957/p/3406448.html

比I麻烦点的就是找到循环开始点TAT

I只是判断是否循环。要求不使用额外空间(不然hash就可以了

按I的思路,我们又慢指针S和快指针F。。。F走两步,S走一步。。。若有环,必定相遇。

画个图(很丑勿喷

假设在红色凸起的地方相遇了。

F走的路程应该是S的两倍

S = x + y

F = x + y + z + y = x + 2y + z

2*S = F

2x+2y = x + 2y + z

得到x = z

也就是从head到环开始的路程 = 从相遇到环开始的路程

那么。。。只要S和F相遇了,我们拿一个从头开始走,一个从相遇的地方开始走

两个都走一步,那么再次相遇必定是环的开始节点!

/**
* 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) {
// IMPORTANT: Please reset any member data you declared, as
// the same Solution instance will be reused for each test case.
if(head == NULL) return NULL;
ListNode* S = head;
ListNode* F = head; while(F != NULL){
if(F) F = F -> next;
if(F) F = F -> next;
if(S) S = S -> next;
if(F != NULL && F == S){
S = head;
while(S != F){
S = S -> next;
F = F -> next;
}
return S;
}
}
return NULL;
}
};

关于此题,网上看到一个更好的解释,解释如下:

转自:http://blog.csdn.net/sysucph/article/details/15378043

对于判断链表是否有环,方法很简单,用两个指针,一开始都指向头结点,一个是快指针,一次走两步,一个是慢指针,一次只走一步,当两个指针重合时表示存在环了。

证明:假设链表有环,环的长度为N,慢指针在起始位置,快指针在位置k(位置从0开始计数),那么快指针只要比慢指针多走经过N-k步,就可以追上慢指针了(因为之前已经多走了k步,在多走N-K步则一共多走了一圈,刚好相遇)。。。,因为每一次快指针都比慢指针多走一步,所以一定可以在有限的步数追上慢指针。

现在的问题是如何求出环的起始位置,我们先给出结论:当快指针和慢指针重合的时候,把一个指针重新指向头指针,两个指针现在速度一样,一次走一步,那么当两个指针值相同时,所在的指针就是我们要找的起始位置。

证明内容来自一个国外的网站:http://umairsaeed.com/2011/06/23/finding-the-start-of-a-loop-in-a-circular-linked-list/

要证明上面这个结论,我们先证明一个结论,假设慢指针Slow停在环的起始位置时,快指针Fast停在第k个位置,那么两个指针相遇时会停在从起始位置倒数第k个位置,也就是n-k这个位置

从Slow停在环的起始位置,假设最终停在n-x相遇。

因为Fast只要再比Slow多走n-k步,就可以追上Slow,而每一次操作Fast都比Slow多走一步,因为只需要再走n-k步就可以追上Slow,此时Slow停在n-k这个位置。

这意味着,如果Slow从环的起始位置,Fast从环的第k个位置开始,最终两个指针会在n-k这个位置相遇(n为环的长度)

假设一开始Fast和Slow从开始位置开始遍历这个链表。

令m = 3,表示经过三步,Slow结点到达环的起始位置,此时Fast在环的第m个位置,因为Fast比Slow多走了m步

根据刚才的结论,当Slow停在起始位置,Fast停在m位置,两个链表最后会在n-m位置相遇

此时把Slow移到头结点位置,两个结点都是要经过m步,才刚刚好到达环的起始位置。

这里好起来好像m小于环的长度l,才成立。其实是一样的。

假设m = t*l+k

这就是说,环最终停在n-k这个位置了。还需要k步就可以到达环的起始结点。而把Slow结点重新设置为头结点,则需要t*l+k步才第一次到达环的起始结点,

但是注意了,多走了k*l步,Fast结点还是会停在环的起始位置的。

得证!!!

和室友大神lyc交流,大神的想了一会,秒了= =!

大神的解释是这样的:假设环的长度为l,从开始到两个指针第一次相遇总共走了m步,那么Fast指针走了2*m步,Slow指针走了m步,Fast比 Slow多走了m步,Fast比Slow多走了x圈,那么有x*l==m,l是m的一个因子,再走m步,两个指针每次走一步,Fast移到开头位 置,Slow走了m步停在第一次相遇位置,Fast因为也是每次走一步,所以也会停在相遇位置,而且可以看出来,一旦Fast进入环,Fast和Slow 结点就保持相对静止了。。。碉堡了。。春哥

Linked List Cycle I&&II——快慢指针(II还没有完全理解)的更多相关文章

  1. [LeetCode题解]142. 环形链表 II | 快慢指针

    解题思路 本题是在141. 环形链表基础上的拓展,如果存在环,要找出环的入口. 如何判断是否存在环,我们知道通过快慢指针,如果相遇就表示有环.那么如何找到入口呢? 如下图所示的链表: 当 fast 与 ...

  2. 【算法分析】如何理解快慢指针?判断linked list中是否有环、找到环的起始节点位置。以Leetcode 141. Linked List Cycle, 142. Linked List Cycle II 为例Python实现

    引入 快慢指针经常用于链表(linked list)中环(Cycle)相关的问题.LeetCode中对应题目分别是: 141. Linked List Cycle 判断linked list中是否有环 ...

  3. Linked List Cycle && Linked List Cycle II

    Given a linked list, return the node where the cycle begins. If there is no cycle, return null. Note ...

  4. LeetCode: Linked List Cycle II 解题报告

    Linked List Cycle II Given a linked list, return the node where the cycle begins. If there is no cyc ...

  5. LeetCode142:Linked List Cycle II

    题目: Given a linked list, return the node where the cycle begins. If there is no cycle, return null. ...

  6. leetcode 141. Linked List Cycle 、 142. Linked List Cycle II

    判断链表有环,环的入口结点,环的长度 1.判断有环: 快慢指针,一个移动一次,一个移动两次 2.环的入口结点: 相遇的结点不一定是入口节点,所以y表示入口节点到相遇节点的距离 n是环的个数 w + n ...

  7. 【LeetCode】142. Linked List Cycle II (2 solutions)

    Linked List Cycle II Given a linked list, return the node where the cycle begins. If there is no cyc ...

  8. LeetCode141 Linked List Cycle. LeetCode142 Linked List Cycle II

    链表相关题 141. Linked List Cycle Given a linked list, determine if it has a cycle in it. Follow up:Can y ...

  9. [算法][LeetCode]Linked List Cycle & Linked List Cycle II——单链表中的环

    题目要求 Linked List Cycle Given a linked list, determine if it has a cycle in it. Follow up: Can you so ...

随机推荐

  1. POJ3974:Palindrome(Manacher模板)

    Palindrome Time Limit: 15000MS   Memory Limit: 65536K Total Submissions: 14021   Accepted: 5374 题目链接 ...

  2. lightoj 1245

    lightoj 1245 Harmonic Number (II) 题意:给定一个 n ,求 n/1 + n/2 + …… + n/n 的值(这里的 "/" 是计算机的整数除法,向 ...

  3. c# 计算时间差---天数

    ---处理两个时间相差的天数 测试数据:三个时间 DateTime dt1 = Convert.ToDateTime("2017-03-17 09:49:55.667"); Dat ...

  4. HDU 5696 区间的价值 暴力DFS

    Problem Description 我们定义"区间的价值"为一段区间的最大值*最小值. 一个区间左端点在L,右端点在R,那么该区间的长度为(R−L+1). 现在聪明的杰西想要知 ...

  5. vs 统计有效代码行数

    1.Visual Studio中,crtl+Shift+F,输入b*[^:b#/]+.*$ ,查找范围:选择整个解决方案,查找选项:使用正则表达式,文件类型:*.cs;*.cshtml  选择查找全部

  6. 上下文管理器 contextlib

    from contextlib import contextmanager @contextmanager def tag(name): print "<%s>" % ...

  7. Mantis 从Windows 迁移到Linux上

    1. 导出windows manits的mysql数据库文件, 在cmd运行:mysqldump -uroot -p3edc$RFV bugtracker > C:/mantis.sql; 2. ...

  8. Spring与MyBatis的整合(山东数漫江湖)

    首先看一下项目结构图: 具体步骤如下: 1.建立JDBC属性文件 jdbc.properties (文件编码修改为 utf-8 ) driver=com.mysql.jdbc.Driver url=j ...

  9. 6、MySQL索引种类

    1.普通索引 这是最基本的索引,它没有任何限制,比如上文中为title字段创建的索引就是一个普通索引,MyIASM中默认的BTREE类型的索引,也是我们大多数情况下用到的索引. –直接创建索引 CRE ...

  10. div+css实现表头固定内容滚动表格

    <div class="m-demo"> <table> <thead> <tr><th>定宽a</th>& ...