链表经典问题汇总

(十六)两个链表相交问题 两个链表相交问题 【题目】给定两个单链表,这两个单链表可能有环,也可能无环。其中头结点分别为head1、head2。实现一个函数,如果两个链表相交,请返回相交的第一个结点;如果不相交返回NULL; 【要求】如果两个链表长度之和为N,时间复杂度要求为O(N),额外空间复杂度为O(1) 【解题思路】 第一步:判断两个链表是否有环,有环返回入环结点,无环返回NULL 判断链表是否有环 第二步:分情况讨论两个链表相交情况 (1)如果两个链表均无环,两个链表相交,那么从相交的部分开始都相等 ,结尾处也一定相 阅读详情

原帖地址http://blog.youkuaiyun.com/vividonly/article/details/6673758

收集了一下链表常见的面试题:

1、如何判断一个单链表有环

2、如何判断一个环的入口点在哪里

3、如何知道环的长度

4、如何知道两个单链表(无环)是否相交

5、如果两个单链表(无环)相交,如何知道它们相交的第一个节点是什么

6、如何知道两个单链表(有环)是否相交

7、如果两个单链表(有环)相交,如何知道它们相交的第一个节点是什么


1、采用快慢步长法。令两个指针p和q分别指向头结点,p每次前进一步,q每次前进两步,如果p和q能重合,则有环。可以这么理解,这种做法相当于p静止不动,q每次前进一步,所有肯定有追上p的时候。

我们注意到,指针p和q分别以速度为1和2前进。如果以其它速度前进是否可以呢?

假设p和q分别以速度为v1和v2前进。如果有环,设指针p和q第一次进入环时,他们相对于环中第一个节点的偏移地址分别为a和b(可以把偏移地址理解为节点个数)

这样,可以看出,链表有环的充要条件就是某一次循环时,指针p和q的值相等,就是它们相对环中首节点的偏移量相等。我们设环中的结点个数为n,程序循环了m次。

由此可以有下面等式成立:(mod(n)即对n取余)

(a+m*v1)mod(n) = (b+m*v2) mod(n)

设等式左边mod(n)的最大整数为k1,等式右边mod(n)的最大整数为k2,则

(a+m*v1)-k1*n = (b+m*v2)-k2*n

整理以上等式:

m= |((k2-k1)*n+a-b)/( v2-v1)|①

如果是等式①成立,就要使循环次数m为一整数。显然如果v2-v1为1,则等式成立。

这样p和q分别以速度为v1和v2且|v2-v1|为1时,按以上算法就可找出链表中是否有环。当然|v2-v1|不为1时,也可能可以得出符合条件的m。

  1. bool IsExitsLoop(slist *head)
  2. {
  3. slist *slow = head, *fast = head;
  4. while ( fast && fast->next )
  5. {
  6. slow = slow->next;
  7. fast = fast->next->next;
  8. if ( slow == fast )break;
  9. }
  10. return !(fast == NULL || fast->next == NULL);
  11. }
bool IsExitsLoop(slist *head) { slist *slow = head, *fast = head; while ( fast && fast->next ) { slow = slow->next; fast = fast->next->next; if ( slow == fast ) break; } return !(fast == NULL || fast->next == NULL); }

时间复杂度分析:假设甩尾(在环外)长度为 len1(结点个数),环内长度为 len2,链表总长度为n,则n=len1+len2。当p步长为1,q步长为2时,p指针到达环入口需要len1时间,p到达入口后,q处于哪里不确定,但是肯定在环内,此时p和q开始追赶,q最长需要len2时间就能追上p(p和q都指向环入口),最短需要1步就能追上p(p指向环入口,q指向环入口的前一个节点)。事实上,每经过一步,q和p的距离就拉近一步,因此,经过q和p的距离步就可以追上p。因此总时间复杂度为O(n),n为链表的总长度。


2、分别从链表头和碰撞点,同步地一步一步前进扫描,直到碰撞,此碰撞点即是环的入口。

证明如下:

链表形状类似数字 6 。

假设甩尾(在环外)长度为 a(结点个数),环内长度为 b 。

则总长度(也是总结点数)为 a+b 。

从头开始,0 base 编号。

将第 i 步访问的结点用 S(i) 表示。i = 0, 1 ...

当 i<a 时,S(i)=i ;

当 i≥a 时,S(i)=a+(i-a)%b 。

分析追赶过程。

两个指针分别前进,假定经过 x 步后,碰撞。则有:S(x)=S(2x)

由环的周期性有:2x=tb+x 。得到 x=tb 。

另,碰撞时,必须在环内,不可能在甩尾段,有 x>=a 。

连接点为从起点走 a 步,即 S(a)。

S(a) = S(tb+a) = S(x+a)。

得到结论:从碰撞点 x 前进 a 步即为连接点。

根据假设易知 S(a-1) 在甩尾段,S(a) 在环上,而 S(x+a) 必然在环上。所以可以发生碰撞。

而,同为前进 a 步,同为连接点,所以必然发生碰撞。

综上,从 x 点和从起点同步前进,第一个碰撞点就是连接点。

  1. slist* FindLoopPort(slist *head)
  2. {
  3. slist *slow = head, *fast = head;
  4. while ( fast && fast->next )
  5. {
  6. slow = slow->next;
  7. fast = fast->next->next;
  8. if ( slow == fast )break;
  9. }
  10. if (fast == NULL || fast->next == NULL)
  11. return NULL;
  12. slow = head;
  13. while (slow != fast)
  14. {
  15. slow = slow->next;
  16. fast = fast->next;
  17. }
  18. return slow;
  19. }
slist* FindLoopPort(slist *head) { slist *slow = head, *fast = head; while ( fast && fast->next ) { slow = slow->next; fast = fast->next->next; if ( slow == fast ) break; } if (fast == NULL || fast->next == NULL) return NULL; slow = head; while (slow != fast) { slow = slow->next; fast = fast->next; } return slow; }

时间复杂度分析:假设甩尾(在环外)长度为 len1(结点个数),环内长度为 len2 。则时间复杂度为“环是否存在的时间复杂度”+O(len1)


3、从碰撞点开始,两个指针p和q,q以一步步长前进,q以两步步长前进,到下次碰撞所经过的操作次数即是环的长度。这很好理解,比如两个运动员A和B从起点开始跑步,A的速度是B的两倍,当A跑玩一圈的时候,B刚好跑完两圈,A和B又同时在起点上。此时A跑的长度即相当于环的长度。

假设甩尾(在环外)长度为 len1(结点个数),环内长度为 len2 ,则时间复杂度为“环是否存在的时间复杂度”+O(len2)。


4、法一:将链表A的尾节点的next指针指向链表B的头结点,从而构造了一个新链表。问题转化为求这个新链表是否有环的问题。

时间复杂度为环是否存在的时间复杂度,即O(length(A)+length(B)),使用了两个额外指针

法二:两个链表相交,则从相交的节点起,其后的所有的节点都是都是两个链表共有的。因此,如果它们相交,则最后一个节点一定是共有的。因此,判断两链表相交的方法是:遍历第一个链表,记住最后一个节点。然后遍历第二个链表,到最后一个节点时和第一个链表的最后一个节点做比较,如果相同,则相交。

时间复杂度:O(length(A)+length(B)),但是只用了一个额外指针存储最后一个节点


5、将链表A的尾节点的next指针指向链表B的头结点,从而构造了一个环。问题转化为求这个环的入口问题。
时间复杂度:求环入口的时间复杂度


6、分别判断两个链表A、B是否有环(注,两个有环链表相交是指这个环属于两个链表共有)

如果仅有一个有环,则A、B不可能相交

如果两个都有环,则求出A的环入口,判断其是否在B链表上,如果在,则说明A、B相交。

时间复杂度:“环入口问题的时间复杂度”+O(length(B))


7、分别计算出两个链表A、B的长度LA和LB(环的长度和环到入口点长度之和就是链表长度),参照问题3。

如果LA>LB,则链表A指针先走LA-LB,链表B指针再开始走,则两个指针相遇的位置就是相交的第一个节点。

如果LB>LA,则链表B指针先走LB-LA,链表A指针再开始走,则两个指针相遇的位置就是相交的第一个节点。

时间复杂度:O(max(LA,LB))

算法大汇总 文章目录 1. 二叉树的最近公共祖先 2. 斐波那契数列 3. 青蛙跳台阶问题 4. 合并两个排序的链表 5. 反转链表 6. 二叉树的镜像 7. 二叉树的深度 8. 顺时针打印矩阵 9. 二叉搜索树的最近公共祖先 10. 两个链表的第一个公共节点 11. 对称的二叉树 12. 最长不含重复字符的子字符串 13. 连续子数组的最大和(最大子数组和) 14. 从尾到头打印链表 15. 删除链表的节点 16. 用两个栈实现队列 17. 求1+2+…+n 18. 平衡二叉树 19. 替换空格 20. 二叉搜索树的 阅读详情

相关推荐

测试dali协议的软件,DALI2.0和DALI1.0完美兼容同一个模块,测试每项可过协议

DALI2.0和DALI1.0完美兼容同一个模块,测试每项可过协议深圳聚积智能 夏先生 13246760327 QQ 349098308■IEC62386-102(V2.0)通过测试内容IEC62386-102/2.1/Test preambleIEC62386-102/3.1/Polarity testIEC62386-102/3.2/Maximum and minimum system v...

weixin_35343788的博客 1349

手把手教你学会简单的链表相交问题(LeetCode 160 .相交链表)

一首歌的时间学会链表相交问题,交给我啦!

qq_52777887的博客 3832

Py6S安装失败?手把手教你解决‘6S executable not found‘错误

本文详细解析了Py6S安装过程中常见的'6S executable not found'错误,提供了从MinGW-w64安装到Fortran编译器配置的完整解决方案。通过优化编译环境和进阶技巧,帮助用户高效完成大气辐射传输建模,提升科学计算效率。

x1y2z的博客 640

链表相交问题详解

但是A链表和B链表的长度不相等,我们怎么才能让curA指向a1的同时cueB指向b2呢?

yyykule的博客 1306

玩转企业微信群机器人:一份超详细的Webhook消息推送指南

企业微信群机器人是一个连接内部协作与外部服务的强大桥梁。通过灵活运用本文介绍的各种消息类型,你可以构建出丰富多彩、信息明确的自动化通知系统,极大地提升团队沟通效率。现在,就动手试试,将你的第一个机器人集成到工作流中吧!如果你有任何有趣的机器人应用场景或遇到了问题,欢迎在评论区留言交流!

代码简单说 Vue、JAVA、PHP、Node.js 熟练运用,接口、架构、性能全搞定。 3974

【GameFramework框架内置模块】15、场景(Scene)

场景(Scene)模块,提供场景管理的功能,负责场景的加载、卸载、切换和管理。可以方便地管理不同场景之间的切换以及不同场景之间的信息传递。

优快云博客专家,Unity3D高级软件工程师,《Unity 3D从入门到实战》作者。 1882

代码随想录链表篇——链表相交(三种方法)

刷题总结

qq_39473176的博客 1384

倍福EL6002做RS232通信获取称重数据..

本文介绍EL6002模块通过RS232自由口通信协议获取从站数据。具体数据对照说明手册即可。

weixin_41883890的博客 1010

两链表相交问题

两单向链表相交问题 一、问题分析 (1)两个链表相交,那么两个链表中的节点一定有相同地址。 (2)两个链表相交,那么两个链表从相交节点开始到尾节点一定都是相同的节点。 (问:为什么? 答:因为每一个节点最多只能有一个下一节点,因此在相交节点之后,链表不可能再分为两个链表) 二、问题解法 根据两个链表是否存在环来分类讨论 1、无环 无环的情况有两种比较快速的解决方式,这两种方...

linchonghui888的博客 2204

AI在生物学领域的应用:基因序列分析和人工智能生物学

好的,非常感谢您提供的这个精彩的主题和详细的要求。我会全力以赴,遵循您的要求写一篇内容丰富、结构清晰、论述深入的专业技术文章。现在,就让我们开始这篇关于"AI在生物学领域的应用:基因序列分析和人工智能生物学"的博客文章吧! 1. 背景介绍 1.1 生物信息学的兴起

AI天才研究院 1413

【PX4学习笔记】1. ROS及PX4环境搭建

环境 Ubuntu18.04 安装教程参考 https://www.guyuehome.com/8983 安装过程中问题的解决 问题1 rosdep init 错误的终极解决方法 注意etc/下的ros和rostep文件夹要自己建 问题2 Ubuntu安装ROS报错 sudo: rosdep:找不到命令 问题3(更好地解决了问题1、2)【推荐】 解决GitHub的raw.githubusercontent.com无法连接问题 问题4:GeographicLib的安装 教程中安装GeographicLib d

【人工智障 | 计算鸡视觉 | 机器孩】 8230

(二) 链表 - 经典问题汇总

(一)找到链表的倒数第n个节点    1.这个问题不难,我们可以两次遍历链表,第一遍记录链表的长度L,第二遍从头遍历链表,找到L-n+1的位置的节点,然后输出,这样时间复杂度为o(n),空间复杂度为o(1)    2.上面的方法看起来不错,但是我们还可以有更好的方法,我们仅仅使用一次遍历就可以,我们使用两个指针slowNode和fastNode来一起遍历,两个指针都指向链表头结点,仅当fastNo...

zz0129的博客 303

Matplotlib之bar3d画3D柱状图

3D柱状图通常用于展示数据集中不同分类项的数据大小或数量。与普通的柱状图相比,3D柱状图更适合展示数据的三个维度 3D 柱状图 按行/列涂颜色 柱加阴影、描黑边 自定义座标轴名、刻度标签、范围

我走的每一步都算数 1120

链表有无环经典问题汇总

参考 http://blog.youkuaiyun.com/vividonly/article/details/6673758

nanjunxiao的专栏 832

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

数据结构面试经典问题汇总

数据结构面试经典问题汇总参考资源:基础深入补充: 参考资源: 基础 数据结构常见面试题 深入 数据结构面试题(三) 数据结构面试必问 数据结构算法常见面试考题 补充: 1.数组和链表的区别,请详细解释。 从逻辑结构来看: a) 数组必须事先定义固定的长度(元素个数),不能适应数据动态地增减的情况。当数据增加时,可能超出原先定义的元素个数;当数据减少时,造成内存浪费;数组可以根据下标直接存取。 b) 链表动态地进行存储分配,可以适应数据动态地增减的情况,且可以方便地插入、删除数据项。(数组中插入、删除

weixin_47219428的博客 1万+

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

力扣刷题记录-链表相关问题

链表相关题目整理

qq_41857397的博客 1069

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

leetcode 常考链表面试题总结

文章目录一. leetcode203 移除链表元素 一. leetcode203 移除链表元素 原题链接: 移除链表元素 第一种方法: 直接删除法 这种方法需要特殊考虑头结点的删除情况 首先考虑一般情况 ,删除的不是头结点,定义两个指针 prev , cur 一前一后,逐步删除移动 我们由图中可以看到,如果删除的是头结点,prev->next = cur->next 该步就会出错,因为 prev 此时是空指针 删除头结点的情况如下: 给出代码 : struct ListNode* remove

DR5200的博客 2521

链表小结(面试必备)

链表经典题目汇总 下面给出关于链表的经典题目,由易入难。多画图都很好理解! 1.leecode:反转链表 利用preprepre,curcurcur 这两个指针和 temptemptemp 这个临时指针,一次循环遍历即可。 循环解法: class Solution: def reverseList(self, head: ListNode) -> ListNode: ...

weixin_42564710的博客 265

Leetcode记录库数据结构篇之一:链表

Leetcode记录库

NotLency的博客 383

经典算法题汇总

链表 链表第一个公共节点:1) 利用栈先进后出,用两个栈对两个链表从头至尾遍历,那么栈顶就为链表的尾节点,依次弹出两个栈,直到弹出的元素不一样时,前一个相同的即为第一个公共节点. 2)分别遍历一次两个链表,算出长度差L,让长的链表的指针先走L步,然后两个指针同时移动,那么第一次指向同样节点的即为公共节点 判断是否存在环:两个指针,每次慢指针走1步,快指针走2步,如果快的最后追上慢的,那么有环...

一番の宝物 3445

Leetcode刷题之链表

1、(141) 环形链表 给定一个链表,判断链表中是否有环。 /** * Definition for singly-linked list. * class ListNode { * int val; * ListNode next; * ListNode(int x) { * val = x; * next = null; * } * } */ //解法一:哈希表,当要存入的节点,已经存在与哈希表中,说明链表有环,遍历.

qq_39305378的博客 225

【刷题】链表

系列汇总:《刷题系列汇总》 文章目录——————《总结汇总》—————————————《剑指offeer》———————1.2.3.4.5.6.7.8.——————《LeectCode》———————1.2.3.4.5.6.7.8.9.10. ——————《总结汇总》——————— ——————《剑指offeer》——————— 1. 题目描述: 优秀思路: 2. 题目描述: 优秀思路: 3. 题目描述: 优秀思路: 4. 题目描述: 优秀思路: 5. 题目描述: 优秀思路:

咸粥的博客 402
上一篇: 素数环
下一篇: 约瑟夫环
zhouxf_cn
博客等级 码龄14年 54粉丝 24原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值