问题
在本题中,单链表可能有环,也可能无环。给定两个单链表的头节点head1
和head2,这两个链表可能相交,也可能不相交,请实现一个函数,如果两个
链表相交,请返回相交的第一个节点;如果不相交,返回null即可。要求:
如果链表1长度为N,链表2的长度为M,时间复杂度请达到O(N+M),额外空间
复杂度请达到O(1)。
本题可以分化成3个小问题
判断单链表是否有环
求两个无环单链表第一个相交的节点
求两个有环单链表第一个相交的节点
环和相交的图例
我们可以先把每一个小问题都解决了再回头看整道题
思路
问题1:判断单链表是否有环,附加条件:如有环,返回第一个入环的节点
判断单链表是否有环有两种思路:
一是使用HashSet,遍历链表判断节点是否存在,若不存在则放入set中,利用set的数据具有唯一性的特点,若节点已存在于set中,则表明是有环的。第一个入环的节点就是第一个重复的节点。
二是快慢指针法,设置快慢指针,快慢指针重合在一起则表明有环。快慢指针重合时把快指针移动到链表的头部,然后两指针都按一次一步移动,再次重合的位置则是入环的节点。(不要问我为什么,我也很迷)
问题2:求两个无环单链表第一个相交的节点
若两个链表都没环,有两种方式获取第一个相交的节点
一是使用Map,遍历head1的链表并放入map中,再遍历head2判断是否存在于map中,存在(第一个)则返回,若无则表明不相交。
二是计算两个链表的长度并保存两者最后的节点地址,若最后节点相等则必定相交,那么如何获取第一个相交节点呢?很简单,把两者的长度相减,让两条链表中较长的走相应的步数,这样大家都站在同一起跑线上了,两条链表同时移动,每次一步,当他们重合的时候即为第一个相交节点。
此为两个链表无环。
注:一个有环一个没环相交,在单链表中是不存在,请读者自行画图。
问题3:求两个有环单链表第一个相交的节点
两个链表有环有一下三种情况,
我们上面已经得出第一个入环节点(下面称loop1/loop2)。
- 若loop1 == lopp2 则是入环前相交。
- 若loop1 != loop2 ,且在loop1进行一轮循环内找到与loop2相等的节点,则是入环后相交
- 剩下的情况则为不相交
判断完情况后就要求出第一个相交的节点
入环前相交:因为是在入环前就相交了,把从入环之后的节点全部无视掉,就可以用两个无环链表相交的做法,求出了。
入环后相交:直接返回loop1或者loop2即可。
下面来看下具体实现。
实现
1 |
|