找含单链表的环入口点

问题1:怎样推断单链表中是否存在环(即下图中从结点E到结点R组成的环)?

分析:设一快一慢两个指针(Node *fast, *low)同一时候从链表起点開始遍历,当中快指针每次移动长度为2。慢指针则为1。则若无环,開始遍历之后fast不可能与low重合,且fast或fast->next终于必定到达NULL;若有环。则fast必定不迟于low先进入环,且因为fast移动步长为2,low移动步长为1,则在low进入环后继续绕环遍历一周之前fast必定能与low重合(且必定是第一次重合)。于是函数可写例如以下:

bool hasCircle(Node* head, Node* &encounter)
{
Node *fast = head, *slow = head;
while(fast && fast->next)
{
fast = fast->next->next;
slow = slow->next;
if(fast == slow)
{
encounter = fast;
return true;
}
}
encounter = NULL;
return false;
}

问题2:若存在环,怎样找到环的入口点(即上图中的结点E)?

解答:如图中所看到的。设链起点到环入口点间的距离为x,环入口点到问题1中fast与low重合点的距离为y。又设在fast与low重合时fast已绕环n周(n>0),且此时low移动总长度为s,则fast移动总长度为2s。环的长度为r。则

        s + nr = 2s,n>0       ①

        s = x + y              ②

       由①式得  s = nr                

       代入②式得

       nr = x + y

       x = nr - y               ③

       现让一指针p1从链表起点处開始遍历,指针p2从encounter处開始遍历,且p1和p2移动步长均为1。则当p1移动x步即到达环的入口点,由③式可知,此时p2也已移动x步即nr
- y步。

因为p2是从encounter处開始移动。故p2移动nr步是移回到了encounter处,再退y步则是到了环的入口点。也即,当p1移动x步第一次到达环的入口点时。p2也恰好到达了该入口点。于是函数可写例如以下:

Node* findEntry(Node* head, Node* encounter)
{
Node *p1 = head, *p2 = encounter;
while(p1 != p2)
{
p1 = p1->next;
p2 = p2->next;
}
return p1;
}

原文来自:http://blog.csdn.net/wuzhekai1985/article/details/6725263

有错误欢迎提出, 分享请标明出处, 谢谢!

感觉好的话就顶一个。 感觉不错的话就踩一个。

菜鸟系列之C/C++经典试题(七)的更多相关文章

  1. 菜鸟系列之C/C++经典试题(三)

    设计包括min函数的栈 题目:定义栈的数据结构,要求加入一个min函数,可以得到栈的最小元素.要求函数min.push以及pop的时间复杂度都是O(1). 分析:这是2006年google的一道面试题 ...

  2. 菜鸟系列 Golang 实战 Leetcode —— 面试题24. 反转链表

    定义一个函数,输入一个链表的头节点,反转该链表并输出反转后链表的头节点.   示例: 输入: 1->2->3->4->5->NULL 输出: 5->4->3- ...

  3. js经典试题之w3规范系列

    js经典试题之w3规范系列 1:w3c 制定的 javascript 标准事件模型的正确的顺序? 答案:事件捕获->事件处理->事件冒泡 解析:先事件捕获从windows > doc ...

  4. 开心菜鸟系列----函数作用域(javascript入门篇)

      1 <!DOCTYPE html>   2 <html>   3 <script src="./jquery-1.7.2.js"></ ...

  5. 开心菜鸟系列----变量的解读(javascript入门篇)

                       console.info(         console.info(window['weiwu'])          console.info(window. ...

  6. js经典试题之常用的方法

    js经典试题之常用的方法 1.下面代码输出的值 let s = "bob" const replaced = s.replace('b', 'l') replaced === &q ...

  7. js经典试题之运算符的优先级

    js经典试题之运算符 1.假设val已经声明,可定义为任何值.则下面js代码有可能输出的结果为: console.log('Value is ' + (val != '0') ? 'define' : ...

  8. js经典试题之ES6

    js经典试题之ES6 1:在ECMAScript6 中,Promise的状态 答案:pending  resolved(fulfilled) rejected 解析: Promise对象只有三种状态: ...

  9. js经典试题之原型与继承

    js经典试题之原型与继承 1:以下代码中hasOwnProperty的作用是? var obj={} …….. obj.hasOwnProperty("val") 答案:判断obj ...

随机推荐

  1. SQL Server 判断表中是否存在某字段

    功能:判断表中是否存在某字段,若不存在,则新增该字段 语句: IF NOT EXIST (SELECT 1 FROM [DATABASE].[SCHEMA].SYSCOLUMNS WHERE ID=O ...

  2. [一个经典的多线程同步问题]解决方案一:关键段CS

    前面提出了一个经典的多线程同步互斥问题,本篇将用关键段CRITICAL_SECTION来尝试解决这个问题. 本文先介绍如何使用关键段,然后再深层次的分析下关键段的实现机制和原理. 关键段CRITICA ...

  3. FASTCGI程序,做个备份,以后用

    11FastCGI 用来作为 Web 服务器的设计方案,有着很多优点.要搭建这样一个服务,有一个最简单的办法来搭建,可以使用 Apache 以及 mod_fcgid 模块来实现. 鉴于网上有关 Fas ...

  4. javamail发送二进制流附件的问题

    最近做个邮件发送功能,要内嵌图片并有附件. 需求很奇怪,图片和附件文件是放在ftp服务器上的,查了下javamail的文档. 添加附件方法如下 MimeBodyPart messageBodyPart ...

  5. Docker背后的容器管理——Libcontainer深度解析

    Libcontainer 是Docker中用于容器管理的包,它基于Go语言实现,通过管理namespaces.cgroups.capabilities以及文件系统来进行容器控制.你可以使用Libcon ...

  6. 创见WiFi SD卡破解之路

    我最近搞了张Transcend WiFi SD,颇为得意.它可以让我在几秒钟内将单反(奶昔,相当便携)中拍摄的照片传到任何支持wifi的设备上.我很喜欢在旅途中拍摄和分享图片,所以对我而言,可以无线传 ...

  7. hdoj 5249 KPI(treap)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5249 思路分析:使用queue记录管道中的值并使用treap能够查询第K大的功能查询第floor(m/ ...

  8. echarts 应用数个样例

    应用一:环形图和饼图嵌套 先说明一下内部文件分布: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdGV4dGJveQ==/font/5a6L5L2T/fo ...

  9. Oracle 表三种连接方式(sql优化)

    在查看sql执行计划时,我们会发现表的连接方式有多种,本文对表的连接方式进行介绍以便更好看懂执行计划和理解sql执行原理. 一.连接方式: 嵌套循环(Nested Loops (NL)) (散列)哈希 ...

  10. 如何判断一个变量是数组Array类型

    在很多时候,我们都需要对一个变量进行数组类型的判断.JavaScript中如何判断一个变量是数组Array类型呢?我最近研究了一下,并分享给大家,希望能对大家有所帮助. JavaScript中检测对象 ...