数据结构与算法面试之链表问题集锦(下)

Posted 码农有道

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构与算法面试之链表问题集锦(下)相关的知识,希望对你有一定的参考价值。

链接:wuchong.me/blog/2014/03/25/interview-link-questions/

码农有道

 




在一文中总结了面试中几个关于链表常见的面试题:O(1)时间删除链表节点、单链表转置、求链表倒数第K个节点、求链表的中间节点。本文继续总结其它常见的链表面试题如判断链表是否有环、是否相交等等。

判断单链表是否存在环

题目描述输入一个单向链表,判断链表是否有环?

分析通过两个指针,分别从链表的头节点出发,一个每次向后移动一步,另一个移动两步,两个指针移动速度不一样,如果存在环,那么两个指针一定会在环里相遇。

代码如下



找到环的入口点


题目描述输入一个单向链表,判断链表是否有环。如果链表存在环,如何找到环的入口点?

分析由上题可知,按照 p2 每次两步,p1 每次一步的方式走,发现 p2 和 p1 重合,确定了单向链表有环路了。接下来,让p2回到链表的头部,重新走,每次步长不是走2了,而是走1,那么当 p1 和 p2 再次相遇的时候,就是环路的入口了。

为什么假定起点到环入口点的距离为 a,p1 和 p2 的相交点M与环入口点的距离为b,环路的周长为L,当 p1 和 p2 第一次相遇的时候,假定 p1 走了 n 步。那么有:p1走的路径: a+b = n;p2走的路径: a+b+k*L = 2*n; p2 比 p1 多走了k圈环路,总路程是p1的2倍

根据上述公式可以得到 k*L=a+b=n显然,如果从相遇点M开始,p1 再走 n 步的话,还可以再回到相遇点,同时p2从头开始走的话,经过n步,也会达到相遇点M。

显然在这个步骤当中 p1 和 p2 只有前 a 步走的路径不同,所以当 p1 和 p2 再次重合的时候,必然是在链表的环路入口点上。

代码如下

【数据结构与算法】面试之链表问题集锦(下)



判断两个链表是否相交


题目描述给出两个单向链表的头指针(如下图所示),判断这两个链表是否相交。这里为了简化问题,我们假设两个链表均不带环。

【数据结构与算法】面试之链表问题集锦(下)

分析

1、直接循环判断第一个链表的每个节点是否在第二个链表中。但,这种方法的时间复杂度为O(Length(h1) * Length(h2))。显然,我们得找到一种更为有效的方法,至少不能是O(N^2)的复杂度。

2、针对第一个链表直接构造hash表,然后查询hash表,判断第二个链表的每个节点是否在hash表出现,如果所有的第二个链表的节点都能在hash表中找到,即说明第二个链表与第一个链表有相同的节点。时间复杂度为为线性:O(Length(h1) + Length(h2)),同时为了存储第一个链表的所有节点,空间复杂度为O(Length(h1))。是否还有更好的方法呢,既能够以线性时间复杂度解决问题,又能减少存储空间?

3、转换为环的问题。把第二个链表接在第一个链表后面,如果得到的链表有环,则说明两个链表相交。如何判断有环的问题上面已经讨论过了,但这里有更简单的方法。因为如果有环,则第二个链表的表头一定也在环上,即第二个链表会构成一个循环链表,我们只需要遍历第二个链表,看是否会回到起始点就可以判断出来。这个方法的时间复杂度是线性的,空间是常熟。

4、进一步考虑“如果两个没有环的链表相交于某一节点,那么在这个节点之后的所有节点都是两个链表共有的”这个特点,我们可以知道,如果它们相交,则最后一个节点一定是共有的。而我们很容易能得到链表的最后一个节点,所以这成了我们简化解法的一个主要突破口。那么,我们只要判断两个链表的尾指针是否相等。相等,则链表相交;否则,链表不相交。

所以,先遍历第一个链表,记住最后一个节点。然后遍历第二个链表,到最后一个节点时和第一个链表的最后一个节点做比较,如果相同,则相交,否则,不相交。这样我们就得到了一个时间复杂度,它为O((Length(h1) + Length(h2)),而且只用了一个额外的指针来存储最后一个节点。这个方法时间复杂度为线性O(N),空间复杂度为O(1),显然比解法三更胜一筹。

代码如下

【数据结构与算法】面试之链表问题集锦(下)



两个链表相交的第一个公共节点


题目描述如果两个无环单链表相交,怎么求出他们相交的第一个节点呢?

分析采用对齐的思想。计算两个链表的长度 L1 , L2,分别用两个指针 p1 , p2 指向两个链表的头,然后将较长链表的 p1(假设为 p1)向后移动L2 - L1个节点,然后再同时向后移动p1 , p2,直到 p1 = p2。相遇的点就是相交的第一个节点。

代码如下

【数据结构与算法】面试之链表问题集锦(下)



扩展:链表有环,如何判断相交


题目描述上面的问题都是针对链表无环的,那么如果现在,链表是有环的呢?上面的方法还同样有效么?

分析如果有环且两个链表相交,则两个链表都有共同一个环,即环上的任意一个节点都存在于两个链表上。因此,就可以判断一链表上俩指针相遇的那个节点,在不在另一条链表上。

代码如下


推荐阅读:




专注服务器后台技术栈知识总结分享

欢迎关注交流共同进步

码农有道 coding


码农有道,为您提供通俗易懂的技术文章,让技术变的更简单!

以上是关于数据结构与算法面试之链表问题集锦(下)的主要内容,如果未能解决你的问题,请参考以下文章

面试算法之链表(C++)

java数据结构与算法之链表相交问题

数据结构与算法(Java)之链表

数据结构与算法之链表

数据结构与算法之链表

JAVA数据结构与算法之链表