先看看原题:《编程之美》3.6编程判断两个链表是否相交,原题假设两个链表不带环。

注:位于(*)符号之间的文字出自于:http://blog.csdn.net/v_july_v/article/details/6447013,作者v_JULY_v。

用指针p1、p2分别指向两个链表头,不断后移;最后到达各自表尾时,若p1==p2,那么两个链表必相交

解法

扩展问题1:如果链表可能有环,上面的方法怎么调整?

分情况讨论:
如果两个链表都没有环,那么同原算法;
如果两个链表一个有环,一个没环,那么必然不相交。
(*)如果两个链表都有环,判断一个链表环上的任一点是否在另一个链表上,如果是,则必相交,反之不相交。这时,需要找到另一个链表完整的环都包括了哪些结点,才能进行判断。(*)
可以看出,解答这个问题要解决判断是否有环。

扩展问题1解法

扩展问题2:如果必须要求出两个链表相交的第一个节点呢?

(*)    思路:如果两个尾结点是一样的,说明它们有重合;否则两个链表没有公共的结点。在上面的思路中,顺序遍历两个链表到尾结点的时候,我们不能保证在两个链表上同时到达尾结点。这是因为两个链表不一定长度一样。但如果假设一个链表比另一个长L个结点,我们先在长的链表上遍历L个结点,之后再同步遍历,这个时候我们就能保证同时到达最后一个结点了。由于两个链表从第一个公共结点开始到链表的尾结点,这一部分是重合的。因此,它们肯定也是同时到达第一公共结点的。于是在遍历中,第一个相同的结点就是第一个公共的结点。在这个思路中,我们先要分别遍历两个链表得到它们的长度,并求出两个长度之差。在长的链表上先遍历若干次之后,再同步遍历两个链表,直到找到相同的结点,或者一直到链表结束。PS:没有处理一种特殊情况:就是一个是循环链表,而另一个也是,只是头结点所在位置不一样。 (*)对于特殊情况,相交的第一个结点可以是第一个链表的表头,也可以是第二个链表的表头。因为从表头开始二者就开始相交了。对于这种情况,如果判断出二者都是循环链表,就可以直接返回其中之一的头指针。

扩展问题2解法

相关问题:求链表倒数第k个结点

(*)设置两个指针p1,p2,首先p1和p2都指向head,然后p2向前走k步,这样p1和p2之间就间隔k个节点,最后p1和p2同时向前移动,直至p2走到链表末尾。(*)

相关问题解法

现在来看,遗留问题是:1.如何判断链表有环?2.如何找到链表环的入口?方法是有的,而且这个算法在3.11节程序改错的扩展问题有所提示。简单来说就是:

对于问题1,指针p1、p2指向表头,每次循环p1指向后继,p2指向后继的后继;循环的结束条件是,p2后继为空(无环)或p1==p2(有环)。

这个方法网上没有看到比较令我满意的解释,而《编程原本》(Elements of Programming)在第2章“变换及其轨道”中虽然有简单的说明,可当时看的时候也不是特别理解(就算现在理解了,这本书上讲得比较抽象,上面的说明放在这里只能让读者越看越糊涂),可能是悟性不够吧。一是不满足于用举例说明,二是觉得,如果是连续地移动,即像物体运动时位移和时间是连续的而不是这样离散的,当然会相遇;而二者都是离散的,如果每次都发生p2刚好越过p1的情况呢?下面用易于理解的方式证明,这个解法中如果有环,p1和p2必同时在停留在某个节点。

如左图,在任意时刻,p1和p2都在环上。由于p1每次向前1步,p2每次向前两步,用相对运动的观点来看,把p1看作静止,那么p2每次相对p1向前1步,二者在顺时针方向上的距离每经过一个时刻就减少1,直到变为0,也即二者恰好相遇。这样就证明了在离散情况下,对于有环链表,二者也是必然在某一时刻相遇在某个节点上的。

沿着这个思路,继续求解问题2寻找环的入口问题。记环的总长度为R(即,环上有R个节点),并将上述的初始时刻选为p1第一次到达环入口的时刻,相遇时p1在环上位置x%R,p2在环位置[2*(L+x)-L]%R,

在相遇点,有(2L+2x-L)%R == x%R,即(L+2x)%R==x%R。根据同余的性质,(L+x)%R==0。

此时把p1放回表头,p2的速度降为1。当p1走了L到达环的入口时,p2在环上的位置为(x+L)%R==0,这意味着p2回到了入口,且与p1相遇。并且由于之前p1不在环上,这是二者的在这一步操作后的第一次相遇,并且都在入口,这便找出了入口的位置。

重述一遍寻找环存在和环入口的方法:

用两个指针p1、p2指向表头,每次循环时p1指向它的后继,p2指向它后继的后继。若p2的后继为NULL,表明链表没有环;否则有环且p1==p2时循环可以终止。此时为了寻找环的入口,将p1重新指向表头且仍然每次循环都指向后继,p2每次也指向后继。当p1与p2再次相等时,相等点就是环的入口。

《编程之美》3.6判断链表是否相交之扩展:链表找环方法证明相关推荐

  1. 编程之美--高效率算出1的数目之扩展问题

    问题:给定一个十进制数N,写下从1开始,到N的所有二进制数,然后数一下其中出现的所有"1"的个数. 问题分析: 十进制 二进制 最右边1的个数总和 倒数第二1的个数总和 倒数第三1 ...

  2. 精选的一些《编程之美》相关资料

    又要到一年的招聘季了,肯定又有很多人开始啃<编程之美>了吧.这本书从开阔视野的角度来说很好,不过限于篇幅,有的问题并没有讲清楚(甚至问题叙述模棱两可.被标榜为"鼓励同面试官交流以 ...

  3. 《编程之美》相关参考资料

    转载自:https://blog.csdn.net/wuyuegb2312/article/details/9896831 为了便于查阅,也为了方便后人不必在搜索上浪费时间,我把比较有价值的文章的链接 ...

  4. java链表实现_数据结构——基于java的链表实现(真正理解链表这种数据结构)...

    一.链表介绍 1.什么是链表? 链表是一种物理存储结构上非连续.非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的.如下图所示,在数据结构中,a1里面的指针存储着a2的地址,这样一个 ...

  5. 编程之美:编程判断两个链表是否相交

    1.问题描述 给出两个单向链表的头指针,比如h1.h2,判断两个链表是否相交.编程之美为了简化问题,假设两个链表均不带环. 如下图: 2.分析与解法 解法一:直观法,先判断第一个链表的每个节点是否在第 ...

  6. 《编程之美》读书笔记(十):“链表相交”扩展问题

    感谢azuryy提供<编程之美>3.6节"链表相交"扩展问题答案 (原博客地址:http://hi.baidu.com/azuryy/blog/item/18e85b0 ...

  7. 【编程题目】编程判断俩个链表是否相交 ☆

    第 7 题(链表) 微软亚院之编程判断俩个链表是否相交 给出俩个单向链表的头指针,比如 h1,h2,判断这俩个链表是否相交. 为了简化问题,我们假设俩个链表均不带环. 问题扩展: 1.如果链表可能有环 ...

  8. 编程之美系列之一——阶乘的运算

    前言:       本人一直以来都对算法很有兴趣,前些日子拿到<编程之美>这本书,爱不释手,遂有意将书中的一些本人觉得较有意思的题目以及自己的心得拿出来与大家分享,共同讨论,共同进步. 需 ...

  9. 面试难,应聘难,好工作,今安在?——《编程之美——微软技术面试心得》为你探路!即将上市,敬请关注!

    这本书是我目前所见到的优秀面试试题的最全集,包含大量有趣且有启发性的题目,一方面对于学生的指导意义重大,另一方面,即使对于我们这些已经工作的人来说,也不失为一本充满智慧与趣味的好书."    ...

最新文章

  1. IC卡读卡器web开发,支持IE,Chrome,Firefox,Safari,Opera等主流浏览 器
  2. windows下mongodb配置
  3. 集合与集合取笛卡尔积
  4. kafka读写 java_java-Kafka流:从应用程序的每个实例中的所有分区读取
  5. 一口气搞懂「链表」,就靠这20+张图了
  6. Day13-日历模块
  7. 动态规划——打家劫舍(Leetcode 198)
  8. homestead 安装mysql8_homestead安装php redis扩展
  9. 【转】vim ctag使用方法
  10. 部署VC2008应用程序
  11. 频率与时间,电容,电感,电阻,计算机,分贝 单位换算
  12. 数字化综合档案管理系统 佰档管家|匠心打造
  13. 软件著作权申请流程和费用
  14. 北京3月去哪玩 赏花踏青登山六大推荐
  15. 11款国外免费主机空间推荐_测试可用
  16. android手机碎片管理,安卓手机如何进行系统碎片整理
  17. Matlab 多层(multi-level)小波分析(dwt,dwt2)
  18. php silk文件转换mp3,微信小程序silk录音文件转mp3
  19. 麻雀要革命2 第31节:不共戴天之仇
  20. 跟着团子学SAP EPPM: CPM主要底表

热门文章

  1. Java基础之IO流
  2. Delphi XE5教程1:语言概述
  3. javascript div 弹出可拖动窗口
  4. 让你彻底明白什么叫游戏引擎(2)
  5. LabView2018的安装
  6. java如何重复userinput_如何使用Scanner Java重复读取用户输入
  7. python public_python中private、protectedamp;public
  8. java判断zip包的编码格式_java解压zip包出现乱码
  9. 360好还是电脑管家好_安装了电脑管家,为什么电脑还是卡?
  10. webview 模拟点击_Android如何基于坐标对View进行模拟点击事件详解