1、 给出两个单向链表的头指针pHead1和pHead2,判断这两个链表是否相交。假设两个链表均不带环。
示意图如下:
如果两个链表相交于某一节点,那么在这个相交节点之后的所有节点都是两个链表所共有的。也就是说,如果两个链表相交,那么最后一个节点肯定是共有的。先遍历第一个链表,记住最后一个节点,然后遍历第二个链表,到最后一个节点时和第一个链表的最后一个节点做比较,如果相同,则相交,否则不相交。时间复杂度为O( len1 + len2),因为只需要一个额外指针保存最后一个节点地址,空间复杂度为O(1)。(编程之美上面有详细的介绍)
2、给出一个单向链表的头指针pHead,判断链表中是否有环。
示意图如下:
链表中有环,其实也就是自相交。我们用两个指针pslow和pfast从头开始遍历链表,pslow每次前进一个节点,pfast每次前进两个结点,若存在环,则pslow和pfast肯定会在环中相遇,若不存在,则pslow和pfast能正常到达最后一个节点(实际上是到达NULL)。
代码如下:
// 判断链表中是否有环
bool IsExitLoop(LinkList *head)
{
LinkList *pslow = head;
LinkList *pfast = head;
while(pfast != NULL && pfast->next != NULL)
{
pslow = pslow->next; // 每次前进一步
pfast = pfast->next->next; // 每次前进二步
if(pslow == pfast) // 两个指针相遇,说明存在环
return true;
}
return false; // 没有环
}
3、给出两个单向链表的头指针pHead1和pHead2,判断这两个链表是否相交,若相交返回第一个相交的节点。假设两个链表均不带环。方法一:
判断两个链表中是否存在地址一致的节点,就可以知道是否相交了。可以对第一个链表的节点地址进行hash排序,建立hash表,然后针对第二个链表的每个节点的地址查询hash表,如果它在hash表中出现,则说明两个链表有共同的结点。这个方法的时间复杂度为:O(max(len1+len2);但同时还得增加O(len1)的存储空间存储哈希表。这样减少了时间复杂度,增加了存储空间。
以链表节点地址为值,遍历第一个链表,使用Hash保存所有节点地址值,结束条件为到最后一个节点(无环)或Hash中该地址值已经存在(有环)。
方法二:
对第一个链表遍历,计算长度len1,同时保存最后一个节点的地址。
对第二个链表遍历,计算长度len2,同时检查最后一个节点是否和第一个链表的最后一个节点相同,若不相同,则不相交,程序结束。
若相交,两个链表均从头节点开始,假设len1大于len2,那么将第一个链表先遍历len1-len2个节点,此时两个链表当前节点到第一个相交节点的距离就相等了,比较下一个节点是不是相同,如果相同就返回该节点(即相交节点),若不相同,两个链表都同步向后走一步,继续比较。
示意图如下:方法三:
由于两个链表都没有环,我们可以把第二个链表接在第一个链表的后面,如果得到的链表有环,则说明这两个链表相交。否则,这两个链表不相交。这样我们就把问题转化为判断一个链表是否有环了。最后,当然可别忘记恢复原来的状态,去掉从第一个链表到第二个链表表头的指向。4、给出一个单向链表的头指针pHead,判断链表中是否有环,若存在,则求出进入环中的第一个节点。示意图如下:红色虚线框中的节点为待求节点。
首先使用第2个题目中的快、慢指针来判断链表是否存在环,若不存在结束。
若链表中存在环,我们从链表头、与两个指针的相遇点分别设一个指针,每次各走一步,两个指针必定相遇,且相遇的第一个点为环的入口点。
代码如下:
// 找到环的第一个入口点
LinkList* FindLoopPort(LinkList *head)
{
LinkList *pslow = head;
LinkList *pfast = head;
while(pfast != NULL && pfast->next != NULL)
{
pslow = pslow->next; // 每次前进一步
pfast = pfast->next->next; // 每次前进二步
if(pslow == pfast) // 两个指针相遇,说明存在环
break;
}
if(pfast == NULL || pfast->next == NULL) // 不存在环
return NULL;
pslow = head;
while(pslow != pfast)
{
pslow = pslow->next; // 每次前进一步
pfast = pfast->next; // 每次前进一步
}
return pslow; // 返回环的入口点
}
分析:当pfast若与pslow相遇时,pslow肯定没有走遍历完链表,而pfast已经在环内循环了n圈(1<=n)。假设pslow走了s步,则pfast走了2s步(pfast步数还等于s 加上在环上多转的n圈),设环长为r,则:
2s = s + nr s= nr
设整个链表长L,入口环与相遇点距离为x,起点到环入口点的距离为a。
a + x = nr 则 a + x = (n – 1)r +r = (n-1)r + L - a a = (n-1)r + (L – a – x)
(L – a – x)为相遇点到环入口点的距离,由此可知,从链表头到环入口点等于(n-1)循环内环+相遇点到环入口点,于是我们从链表头、与相遇点分别设一个指针,每次各走一步,两个指针必定相遇,且相遇第一点为环入口点。
小结:链表是数据结构中最基本的,也是面试中常考的,与链表相关的题目也变化多端,只要基础扎实,多积累一些处理类似问题的技巧,面试时便能应对自如。
分享到:
相关推荐
面试题 02.07. 链表相交原题链接:面试题 02.07. 链表相交解法一:首尾相接法解题思路将这两个链表首尾相连,然后检测这个链表是否存在环,如果存在,则两
不错的毕业设计、课程设计、练手c++语言项目:链表HuffmanTree.rar 不错的毕业设计、课程设计、练手c++语言项目:链表HuffmanTree.rar 不错的毕业设计、课程设计、练手c++语言项目:链表HuffmanTree.rar 不错的毕业...
c语言作业:链表的操作.zipc语言作业:链表的操作.zipc语言作业:链表的操作.zipc语言作业:链表的操作.zipc语言作业:链表的操作.zipc语言作业:链表的操作.zipc语言作业:链表的操作.zipc语言作业:链表的操作....
面试题总结:数组和链表的区别 数组和链表.pdf
使用c语言中的循环链表及结构体实现约瑟夫环问题
删除链表的倒数第N个节点、面试题02.07.链表相交和142.环形链表II。记录了清晰的文字题解+图示以及Java参考代码。 适合人群:链表算法感兴趣的程序员或学生,想要打好数据结构与算法基础的人。 能学到什么:掌握链表...
js代码-面试题9:链表
换句话说,如果一个链表的第k个节点与另一个链表的第j个节点是同一节点(引用完全相同),则这两个链表相交。示例 1:输出:Reference of the nod
C++经典基础题(链表
分析与解法 这样的一个问题,也许我们平时很少考虑。但在一个大的系统中,如果出现两个链表相 交的情况,而且释放了其中一个链表的...的两个链表,我们希望在释放一个链表之前知道是否有其他链表跟当前这个链表相交。
数据结构:链表.ppt
第一百零六天学习记录:数据结构与算法基础:链表Ⅰ(王卓教学视频)配套cpp代码
C++实现链表模板(链表项的数据元素可以为任意类型):链表项的插入、删除、链表的打印、两个链表的连接 开发环境为VS2010
java基础面试题反转链表本资源系百度网盘分享地址
这里面包含链表的几乎所有操作:链表的创建、插入、删除、排序等;
第10讲:链表操作.rar
面试题5:检测一个较大的单向链表是否带环 10.3 双向链表 面试题6:按要求构造一个双向链表 面试题7:编程实现双链表插入新结点 面试题8:编程实现双链表删除指定结点 10.4 栈和队列 面试题9:简述队列和栈的异同 ...
实现了一个简单的java版本的单链表,...关于链表是否相交是一次阿里的面试的在线试题,挂的很彻底。然后就在网上找了几个实现思路自己用java做了一个简单的实现.MyLinkedList.java 是链表的实现,Main.java 是测试代码
算法大全-面试题-链表-栈-二叉树-数据结构