题目

可能有环也可能无环的两个单链表,判断这两个链表是否相交,如果相交返回相交的第一个节点。

解析

第一步,判断链表是有环链表还是无环链表;
如果一个单链表无环,它一定有一个指向null的尾结点;
如果一个单链表有环,用两个指针oneStep,twoStep,twoStep一次走两个节点,oneStep一次走一个节点,这两个指针必定会相遇;
此时将twoStep重新遍历,一次走一个节点,oneStep也继续一次走一个节点,二次相遇的时候,这个节点就是入环节点。

第二步,判断是否相交;
2-1:一个单链表有环,一个单链表无环,这两个单链表一定不想交;
2-2:两个单链表都无环,这两个单链表尾结点相同,则说明它们相交;这两个单链表尾结点不相同,则说明它们不相交。

找相交节点:
两个单链表在遍历时,用一个变量n记录两个单链表的长度差,单链表1遍历时++,单链表2遍历时–,如果n>0说明单链表1长,如果n<0说明单链表2长,如果n=0说明1两个单链表一样长;在重新遍历两个链表,链表长的先遍历n的绝对值个节点,然后两个链表一起前进,第一个相同节点为相交的第一个节点。

2-3:两个单链表都有环,那么有三种情况:

不想交的情况:先找到一个单链表的入环节点node;然后遍历另一个单链表,如果二次到达入环节点都没有找到node,说明这两个链表不相交;如果二次到达入环节点前都找到了node,说明这两个链表相交。

入环节点前相交的情况:上面得知链表相交,如果两个单链表的入环节点相同,则说明它们入环节点前相交;
找相交节点:
如果只看开始节点到入环节点这段链表,则装换成2-2情况。

入环节点后相交的情况:上面得知链表相交,如果两个单链表的入环节点不相同,则说明它们入环节点后相交;
找相交节点:此种情况,两个入环节点都可以说是相交的第一个节点。

代码

public static class Node {public int value;public Node next;public Node(int data) {this.value = data;}
}public static Node getIntersectNode(Node head1, Node head2) {if (head1 == null || head2 == null) {return null;}Node loop1 = getLoopNode(head1);Node loop2 = getLoopNode(head2);if (loop1 == null && loop2 == null) {return noLoop(head1, head2);}if (loop1 != null && loop2 != null) {return bothLoop(head1, loop1, head2, loop2);}return null;
}// 找到链表第一个入环节点,如果无环,返回null
public static Node getLoopNode(Node head) {if (head == null || head.next == null || head.next.next == null) {return null;}Node slow = head.next; Node fast = head.next.next; while (slow != fast) {if (fast.next == null || fast.next.next == null) {return null;}fast = fast.next.next;slow = slow.next;}// slow fast  相遇fast = head; // n2 -> walk again from headwhile (slow != fast) {slow = slow.next;fast = fast.next;}return slow;
}// 如果两个链表都无环,返回第一个相交节点,如果不想交,返回null
public static Node noLoop(Node head1, Node head2) {if (head1 == null || head2 == null) {return null;}Node cur1 = head1;Node cur2 = head2;int n = 0;while (cur1.next != null) {n++;cur1 = cur1.next;}while (cur2.next != null) {n--;cur2 = cur2.next;}if (cur1 != cur2) {return null;}cur1 = n > 0 ? head1 : head2; cur2 = cur1 == head1 ? head2 : head1; n = Math.abs(n);while (n != 0) {n--;cur1 = cur1.next;}while (cur1 != cur2) {cur1 = cur1.next;cur2 = cur2.next;}return cur1;
}// 两个有环链表,返回第一个相交节点,如果不想交返回null
public static Node bothLoop(Node head1, Node loop1, Node head2, Node loop2) {Node cur1 = null;Node cur2 = null;if (loop1 == loop2) {cur1 = head1;cur2 = head2;int n = 0;while (cur1 != loop1) {n++;cur1 = cur1.next;}while (cur2 != loop2) {n--;cur2 = cur2.next;}cur1 = n > 0 ? head1 : head2;cur2 = cur1 == head1 ? head2 : head1;n = Math.abs(n);while (n != 0) {n--;cur1 = cur1.next;}while (cur1 != cur2) {cur1 = cur1.next;cur2 = cur2.next;}return cur1;} else {cur1 = loop1.next;while (cur1 != loop1) {if (cur1 == loop2) {return loop1;}cur1 = cur1.next;}return null;}
}

有苦有乐的算法 --- 可能有环也可能无环的两个单链表,判断这两个链表是否相交,如果相交返回相交的第一个节点相关推荐

  1. 判断两个无环单向链表/有环单向链表是否相交,并返回相交节点

    题目描述:单链表可能有环,也可能无环.给定两个单链表的头节点 head1 和 head2, 这两个链表可能相交,也可能不相交.请实现一个函数,如果两个链表相交,请返回相交 的第一个节点;如果不相交,返 ...

  2. 有苦有乐的算法 --- 并查集的实现原理

    假如有两个集合: 找出一个节点作为集合的'头',集合内的其他节点都与这个'头'进行关联(可以直接找到这个'头'); 如果需要在集合A中查找一个元素是否存在,或者判断两个元素是否属于同一集合,只需判断它 ...

  3. 有苦有乐的算法 --- 获取二叉树的最大宽度

    题目 一颗二叉树,求其最大宽度. 例: 解析 按层遍历二叉树: 在遍历时,使用用4个变量来记录信息: Node curEnd = null; // 当前层,最右节点是谁 Node nextEnd = ...

  4. 有苦有乐的算法 --- 二叉树的按层遍历

    题目 给定一个二叉树,进行按层遍历. 例: 解析 给定一颗二叉树: 首先准备一个队列,让头节点入队: 节点出队并打印,同时此节点的左节点2入队,右节点3在入队: 2出队,2的左节点4入队,2的右节点5 ...

  5. 有苦有乐的算法 --- 判断一颗二叉树是否是完全二叉树、是否是平衡二叉树、是否是搜索二叉树

    是否是完全二叉树 完全二叉树:二叉树的每一层要么是满的,要么从左到右处在变满的路上. public static boolean isCBT(Node head) {if (head == null) ...

  6. 有苦有乐的算法 --- 有序数组中的元素存在问题、最左元素问题和无序数组局部最小问题

    一个有序数组,判断是否含有一个元素 解析: 给定一个数组 如果需要判断是否存在的元素为3. 首先找到数组的中间元素: 如果此元素为3,结束: 如果不是,此元素与3比较,此元素如果大于3,在从此元素左边 ...

  7. 有苦有乐的算法 --- 一个数组中,有两种数出现了奇数次,其余数都出现了偶数次,找到这两种数

    题目 一个数组中,有两种数出现了奇数次,其余数都出现了偶数次,找到这两组数 例: [2,4,3,2,5,4] ⇒ [3,5] [1,4,6,3,7,8,3,2,1,2,6,6,7,8] ⇒ [6,4] ...

  8. 有苦有乐的算法 --- 基数排序

    题目 一个无序数组,使用基数排序的方式从小到大进行排序 解析 给定一个数组: 首先准备一个"桶"(每个桶是一个队列): 从左到右遍历数组,每个元素的个位数是多少,就进入几号桶中: ...

  9. 有苦有乐的算法 --- 随机快排

    题目 使用随机快排对给定数组进行从小到大排序 [5,3,2,1,5] ⇒ [1,2,3,5,5] 解析 给定一个数组 1.在数组中找出一个数作为基准(最右侧的数2):变量l记录数组头位置,变量r记录尾 ...

最新文章

  1. vibe前景提取改进算法
  2. access无法 dolby_如何解决windows 8无法开启杜比音效的问题
  3. html切换选择项,HTML选择选项元素
  4. python 麦克风人声检测_【录音技巧】如何为人声录音 ,防止喷麦
  5. C语言实现ternary search三分查找算法(附完整源码)
  6. 坯子库安装不上_柜式七氟丙烷的安装调试方法
  7. (纪录片)电的故事 Shock Awe The Story of Electricity
  8. java tcp链接慢_jmeter tcp长连接性能测试
  9. PHP实现简单的计算器
  10. 如何在cmd命令提示符里打开Python
  11. 8-BIT OPTIMIZERS VIA BLOCK-WISE QUANTIZATION--通过块级量化的8位优化器
  12. 『paddle』paddleclas 学习笔记:图像识别
  13. 野生二粒小麦基因组在science发布
  14. 参考文献自动生成--
  15. 李佳琦同款美容仪,让护肤品效果翻倍
  16. linux钓鱼邮件,钓鱼邮件传播勒索病毒再升级,不落地加大查杀难度
  17. 脉脉热帖:数仓真的是太无聊了...
  18. ERROR 2002 HY000 Can't connect to local MySQL server thro
  19. 腾讯社招iOS面试记录
  20. bi平台怎么选,一文详解

热门文章

  1. 20162316刘诚昊 第五周作业
  2. weak 属性需要在dealloc中置为nil吗
  3. 详解 ERC-20 vs ERC-777、ERC-721 vs ERC-1155: 它们有何不同?
  4. 混合云的那些事:如何做到让公有云和私有云实现1+12
  5. python题库--简单
  6. Maven 的 Lifecycle 和 plugins
  7. python大佬的可视化工具-Bokeh
  8. HGU3336 Count the string (KMP Next数组的应用)
  9. vue中如何使用SM4国密来加密?
  10. 常青藤爸爸完成5000万元A轮融资,打造四大版块核心业务生态