判断两个单链表是否相交(有环、无环两种)
时间:2022-04-29
本文章向大家介绍判断两个单链表是否相交(有环、无环两种),主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
题目描述:
给定两个单链表的头节点head1和head2,如何判断两个链表是否相交?相交的话返回true,不想交的话返回false。
给定两个链表的头结点head1和head2。请返回一个bool值代表它们是否相交。
链表中节点的类型设置如下:
class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}
思路:
1、首先判断是否有环,
- 若两个链表都没有环,则进行无环单链表判断是否相交,进入2;
- 若两个链表一个有环一个无环,则直接判断不相交;
- 若两个链表都有环,则分别得到每个链表的入环节点node1,node2,然后进行有环单链表判断是否相交,进入3;
判断是否有环的方法如下:
1 /**
2 * 判断链表是否有环
3 * 判断方法是设置两个指针最初均指向头结点,然后fast每次走2步,slow每次走1步,
4 * 如果链表没有环,则fast指针肯定先指向表尾的null
5 * 如果有环,则fast和slow肯定会相遇。然后第一次相遇后我们将fast指针重新指向头结点,
6 * 然后fast和slow每次都走一步直到第二次相遇,那么第二次相遇的节点即为入环的节点
7 * @param head
8 * @return 若有,则返回入环节点,否则,返回null
9 */
10 public ListNode judgeRing(ListNode head){
11 if(head == null){
12 return null ;
13 }
14 ListNode fast = head ;
15 ListNode slow = head ;
16
17 while(fast != null && fast.next != null){
18 fast = fast.next.next ;
19 slow = slow.next ;
20 if(fast == slow){
21 fast = head ;
22 while(fast != slow){
23 fast = fast.next ;
24 slow = slow.next ;
25 }
26 return slow ;
27 }
28 }
29 return null ;
30 }
有环时查找入环点的方法的证明过程如下:
当fast与slow相遇时,slow还没走完链表,而fast已经在环内循环了n圈了,假设slow在相遇前走了s步,则fast走了2s步,设环长为r,有2s=s+nr,即s=nr.
由上图可知a+x=s, x+y=r,而我们的目标是找到a的位置。设上图那个拱起的曲线的长度为y,有a+x=s=nr=(n-1)r+r=(n-1)r+y+x,则a=(n-1)r+y. 这个公式告诉我们,从链表头和相遇点分别设一个指针,每次各走一步,这两个指针必定相遇,且相遇的第一个点为环入口点。
2、无环单链表是否相交判断有多种方法:
-
- 方法1:先循环链表1,将每个节点的地址进行hash计算存入哈希表,然后计算链表2的每个节点的地址的hash值,若与hash表中对应位置有值,则相交,否则不相交。
- 方法2:见链表1与2进行首尾相连,判断新链表是否有环,若没有,则不相交,若有环,则是相交的。
- 方法3:先计算两个链表的长度L1、L2,若L1 > L2,则先将链表1移动(L1 - L2)个节点,等到链表1和链表2剩下的长度一样的时候,一起向后移动,依次判断当前链表的节点是否相等,若相等,则相交,若到队尾还没有相等的,则不相交
方法3的代码如下:
1 /**
2 * 判断两个无环链表是否相交
3 * @param head1
4 * @param head2
5 * @return
6 */
7 public boolean judgeIntersectWithoutRing(ListNode head1,ListNode head2){
8 int len1 = calLen(head1) ;
9 int len2 = calLen(head2) ;
10 ListNode intsect = null ;
11 if(len1 > len2){
12 intsect = judge(head1,len1,head2,len2) ;
13 }else{
14 intsect = judge(head2,len2,head1,len1) ;
15 }
16 //判断相交的节点是否为null,返回结果
17 if(intsect != null){
18 return true ;
19 }else{
20 return false ;
21 }
22 }
23
24 /**
25 * 计算链表的长度并返回
26 * @return
27 */
28 private int calLen(ListNode head){
29 int len = 0;
30 while(head != null){
31 len++ ;
32 head = head.next ;
33 }
34
35 return len ;
36 }
37
38 /**
39 * 按长链表、短链表的顺序传入两个链表,然后进行判断
40 * 如果相交,则输出首次相交的节点,否则输出null
41 * @return
42 */
43 private ListNode judge(ListNode headLong,int lenLong,
44 ListNode headShort,int lenShort){
45 int gap = lenLong - lenShort ;
46 //将较长的链表移动到与短链表等长的位置
47 while(gap != 0){
48 headLong = headLong.next ;
49 }
50 //开始判断
51 while(headLong != null && headShort != null){
52 if(headLong == headShort){
53 return headShort ;
54 }else{
55 headLong = headLong.next ;
56 headShort = headShort.next ;
57 }
58 }
59
60 return null ;
61 }
3、有环单链表是否相交的判断方法:先比较两个链表的入环节点是否相等,若想等,则相交,若不想等,则从某个链表的入环节点开始循环一周,判断是否有节点等于另一个链表的入环节点,若等于,则相交,否则不相交。
这个有环链表的判断是在得到两个环的入环节点的基础上进行的,比较简单,就不放代码了。
- JS魔法堂:判断节点位置关系
- bash/shell编程学习(3)
- Tomcat配置Web程序几种方式
- java并发编程学习: 守护线程(Daemon Thread)
- HTML条件注释判断浏览器及检验
- HttpClient(二)HttpClient使用Ip代理与处理连接超时
- JavaScript中匿名函数的困惑
- 基础野:细说有符号整数
- Ubuntu14.04下如何开启Mysql远程访问
- docker学习(7) docker-compose使用示例
- docker学习(3) 容器的启动过程
- 基础野:细说原码、反码和补码
- JavaScript循环读书笔记
- docker学习(2) mac中docker-machine使用vmware fusion以及配置国内镜像加速
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- android 使用kotlin 实现点击更换全局语言(中日英切换)
- EasySec基于XP的渗透平台
- Android集成腾讯X5实现文档浏览功能
- 8个小时8个小时的上机课!!
- Android实现根据评分添加星级条
- Android悬浮窗的实现(易错点)
- phpcms上传导致getshell详解及案例
- android popupwindow用法详解
- SpringAOP + 注解实现日志管理
- 删除一个表中所有含重复字段的数据
- stm32mp157开发板常用系统工具使用
- android实现筛选菜单效果
- AppCMS注入及评论xss漏洞
- css属性为 { flex: 1 }时表示的意思
- Android studio 实现手机扫描二维码功能