带环链表 II

单链表,问有没有环,若有,找到环的入口.

Lintcode上挑战,只许使用常数的空间.

设一个快指针fast,一个慢指针slow,fast每次走2步,slow每次走1步.

若无相遇找到了链尾,则无环,若相遇了,则有环.

设从链头到环入口点走了a步,从环入口到相遇点走了x步,环长r.相遇时,slow走了s步,fast走了2s步.

有:

s=a+x,  2s=a+nr+x.

所以a+x=nr->a=nr-x.

注意理解a=nr-x.意思是从链头走到环入口的 步数=再走n圈,并退x步.那刚好也在环入口.

 1 class Solution {
 2 public:
 3     ListNode *detectCycle(ListNode *head) {
 4         ListNode *slow = head, *fast = head;
 5         while (fast && fast->next) {
 6             slow = slow->next;
 7             fast = fast->next->next;
 8             if (slow == fast)
 9                 break;
10         }
11         if (!fast || !fast->next)
12             return NULL;
13         slow = head;
14         while (slow != fast) {
15             slow = slow->next;
16             fast = fast->next;
17         }
18         return slow;
19     }
20 };
时间: 2024-11-08 19:23:35

带环链表 II的相关文章

[LintCode] Linked List Cycle(带环链表)

描述 给定一个链表,判断它是否有环. 样例 给出 -21->10->4->5, tail connects to node index 1,返回 true. 这里解释下,题目的意思,在英文原题中,tail connects to node index 1 表示的是节点 5 还要链接回索引号 为 1 的节点. 一个典型的带环链表如下: 挑战 不要使用额外的空间 代码 GitHub 的源代码,请访问下面的链接: https://github.com/cwiki-us/java-tutoria

带环链表的入口

带环的单链表: 如上图,List 为一个带有环的单链表,环的大小为5: 证明: S 为 slow 指针相遇前走的距离,2S 为 fast 指针相遇前走过的距离: ∵ 2S = S + n*R;        //n slow,fast指针相遇前 fast 多经历的圈数  S = H_I + R1: ∴S = n*R; ∴n*R = H_I  + R1; ∵ R1 + R2 = R; ∴(n-1)*R = H_I - R2; ∴(n-1)*R + R2 = H_I;       //结论:(交点到

[PHP] 算法-请找出带环链表的环的入口结点的PHP实现

给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null 1.找链表倒数第k个结点,输入一个链表,输出该链表中倒数第k个结点.第一个指针走(k-1)步,到达第k个节点,两个指针同时往后移动,当第一个结点到达末尾的时候,第二个结点所在位置就是倒数第k个节点了 2.原理有点像上面的,定义两个指针,一个是快指针每次走两步,一个是慢指针每次走一步,当两个相遇的时候,假设环的长度为n个结点,慢指针走x步,快指针走2x步,2x=x+kn ;x=kn; k暂时假定为1圈 ,也就是慢指针slow

关于相交链表、带环链表、链表深拷贝的思路整理

返回相交链表的交点:1.先求出两个链表的各自长度2.让长的先走他们的(长度差)步3.然后两者同时走,第一次相遇就是交点(返回该结点) 判断链表是否带环:1.快慢指针(快的走两步,慢的走一步,不能一个一步,一个n步(N>2),可能会错过)2.如果两个指针相遇,则链表带环:如果快的遇到null,则不带环(直线形) 求入环点:1).转化为相交问题(求取相遇结点)2).一个从起点,一个从交点,都每次走一步,第一次相遇点为入环点 相交+带环(六种情况) 复杂链表的复制1)简单复制无法解决(因为是浅拷贝)2

判断两个链表是否相交(带环)

解决方案: 1.找出链表1的环入口节点a1,链表2的环入口节点a2; 2.如果a1=a2; 说明两个链表可能在入环之前或者入环第一个节点相交:将a1,a2作为两个链表的最后一个节点,转化为不带环的链表相交:其实在这种情况下已经说明两个链表已经相交了. 3.如果a1!=a2;以a1为基准节点进行while循环,如果在循环中找到跟a2相同的节点,说明两个链表相交:如果没找到,说明不相交. #如果1个链表不带环,1个链表带环:则两个链表必不相交:

带环单链表

判断单链表是否带环: 定义两个快慢指针,快指针每次走两步,慢指针每次走一步,然后判断是否两个指针相遇.若相遇,则带环. 设慢指针走过的路程为s,则快指针走过的路程即为2s. 设从环头结点到环的入口点的距离为a. 设从环的入口点到两指针相遇点的距离为x. 设环的长度为m.快指针走了n圈. 由数学关系式可得:s = a + x    2s = a + n*m + x; 则  n*m = a + x; a = n*m - x; 求环的入口点方法:定义连个指针,一个指针从环的头结点开始走,另一个指针则从

判断链表是否带环,若带环,找到环的入口点

#pragma once #include<iostream> using namespace std; template<class T> struct LinkNode { T _data; LinkNode* _next; LinkNode(const T& x) :_data(x) , _next(NULL) {} }; template<class T> class ListNode { //为了安全性 private: ListNode(const 

c/c++单链表面试题—链表带环问题

1.判断一个单链表是否带环 思路解析: 判断一个单链表是不是带环,就看在遍历单链表的时候能不能遍历完成,如果带环的话会陷入死循环程序一直无法结束,但是这种判断方法在程序的实现是不可能的.所以转换一种思路,利用两个遍历速度不同的指针遍历,如果存在环的话,那么快指针迟早会追上慢指针.通过这个判断程序实现起来是比较简单可行的. 单链表的结构体及其类的定义 struct Node { public: Node(const DataType& d) :_data(d) ,_next(NULL) {} pu

单链表的插入 删除 及带环 问题

#include<stdio.h> #include<assert.h> #include<malloc.h> #include<stdlib.h> typedef int Datatype; typedef struct SListNode { Datatype data; struct SListNode*next; }SListNode; void Erase(SListNode*&pHead, SListNode *pos); void Pu