如果单链表有环,求环的起始位置

问题:如果单链表中存在环,求环的起始位置

解:在上篇文章中,利用追逐法判断一个单链表是否存在环。求环的起始位置,需要求解单链表的长度和环的长度的关系。如果确定了单链表的长度和环的长度的关系,那么环的起始位置就呼之欲出了。

在判断单链表中有两个指针P和q,p每次前进两步,q每次前进一步,p的速度是q的两倍。设单链表的长度为L,环的长度为R,链表起点到环起点的距离为X,当p和q相遇时,慢指针总共走了S步,在环内总共走了a步,快指针总共走了2S步,此时满足:2S=S+n*R,所以S=n*R。

S=X+a;

X+a=(n-1)*R+R=(n-1)*R+L-X

X=(n-1)*R+L-X-a

其中(n-1)*R+L-X表示相遇的位置,L-X表示环的长度,L-X-a表示相遇点到达环起始位置的距离。也就是说,链表起点到环起点的距离X等于从相遇位置到达环起点的距离。这一结论是解决这道题的理论基础。当快慢指针相遇后,让快指针p重新指向链表的起点位置,重新设置p的速度和q的速度相同,当p和q再次相遇时的位置就是环的起始位置。具体实现代码如下:

 1 linkNode *circleStart(linkNode *head)
 2
 3 {
 4 linkNode *p,*q;
 5 p=q=head;
 6 while(p!=null && p->next!=null)
 7 {
 8 p=p->next->next;
 9 q=q->next;
10 if(p==q)
11 break;
12 }
13 if(p==q &&p!=null)
14 {
15 p=head;
16 while(p!=q)
17 {
18 p=p->next;
19 q=q->next;
20 }
21 return p;
22 }
23 else{
24 return null;
25 }
26 }
时间: 2024-12-23 19:14:49

如果单链表有环,求环的起始位置的相关文章

数据结构和算法设计专题之---判断单链表中是否有环,环的长度,环的入口节点

题目: 给定一个单链表,只给出头指针head: 1.如何判断是否存在环? 2.如何知道环的长度? 3.如何找出环的连接点在哪里? 4.带环链表的长度是多少? 解法: 1.对于问题1,使用追赶的方法,设定两个指针slow.fast,从头指针开始,每次分别前进1步.2步.如存在环,则两者相遇:如不存在环,fast遇到NULL退出. 2.对于问题2,记录下问题1的碰撞点p,slow.fast从该点开始,再次碰撞所走过的操作数就是环的长度s. 3.问题3:有定理:碰撞点p到连接点的距离=头指针到连接点的

判断单链表里面有没有环

原文链接:http://www.cnblogs.com/zhyg6516/archive/2011/03/29/1998831.html 这题目还是挺有意思的. 题目:0.如何判断单链表里面是否有环? 算法的思想是设定两个指针p, q,其中p每次向前移动一步,q每次向前移动两步.那么如果单链表存在环,则p和q相遇:否则q将首先遇到null. 这里主要理解一个问题,就是为什么当单链表存在环时,p和q一定会相遇呢? 假定单链表的长度为n,并且该单链表是环状的,那么第i次迭代时,p指向元素i mod

[算法天地]关于单链表的操作有环无环判断

#include <stdio.h> #include <stdlib.h> // 有环链表的各种函数测试 typedef struct Node { int data; struct Node *next; }Node; typedef struct Node* LinkList; /*链表初始化*/ int InitList(LinkList *L) { *L = (LinkList)malloc(sizeof(Node)); if(!(*L)) return -1; (*L)

判断单链表中是否有环(循环链表)

有环的定义:链表的尾结点指向了链表中的某个结点,如下图所示 判断是否有环,两种方法: 方法1:使用p.q两个指针,p总是向前走,但q每次都从头开始走,对于每个节点看p走的步数和q是否一样,如上图所示:当p从6走到3时,共走了6步,此时若q从出发,则q只需要走两步就到达3的位置,因而步数不相等,出现矛盾,存在环. 方法2:快慢指针,定义p.q两个指针,p指针每次向前走一步,q每次向前走两步,若在某个时刻出现 p == q,则存在环. 具体代码实现: 1 #include<stdio.h> 2 #

链表——将单链表从m到n的结点位置翻转

题目:反转链表从m-n位置的结点 For example: Given1->2->3->4->5->NULL, m = 2 and n = 4, return1->4->3->2->5->NULL. 从第二到第四的结点被反转了. 其中m和n满足条件: 1 ≤ m ≤ n ≤ length of list. 思路: 仍是逆序,仍考虑到用辅助空间stack. 将m-n的结点依次入栈,并标记与入栈结点相邻的前后两个结点pfirst和psecond (若

单链表的经典操作,查找链表倒数第k个节点,判断链表是否存在环,求环节点

#include<stdio.h>#include<stdlib.h> typedef struct date_list{    int data;    struct date_list* next;}mylist; mylist* creatlist(int x,mylist* p)        //用一个元素创建链表{    if(NULL == p)                         //链表创建必须判空    {        p = malloc(siz

单链表是否有环的问题解决与讨论(java实现)

单链表是否有环的问题经常在面试中遇到,一般面试中会要求空间为O(1);再者求若有环,则求环产生时的起始位置. 下面采用java实现. //单链表class ListNode{ int val; ListNode next; ListNode(int x){ val=x; next=null; } } public class SearchCycleNode{ ListNode equalListNode=null;//来记录判断有环时出现的相等的时的节点,姑且叫"相遇"节点. //从&

[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? 这个求单链表中的环的起始点是之前那个判断单链表中是否有环的延伸,可参见我之前的一篇文章 (http://www.cnblogs.com/grandyang/p/4137187.html). 还是要设

单链表 --- 环相关问题(是否存在环、是否相交)

一.两单链表皆不带环 ---> 是否存在"环"及 环长 方法:借助于 快慢指针 ,两指针是否存在相遇情况(存在,即存在环:反之,不存在) 环长:相遇时开始计算慢指针所走过距离,即为环长 int IsCycle(ListNode *_head)  //是否存在环 及 环长(两链表不带环) { ListNode *fast=_head; ListNode *slow=_head; while (fast&&fast->_next&&fast-&g