找出两个链表的第一个公共节点

问题描述
输入两个链表 , 找出它们的第一个公共节点 。
如下面的两个链表:

找出两个链表的第一个公共节点

文章插图
 
在节点 c1 开始相交 。
 
示例 1:
找出两个链表的第一个公共节点

文章插图
 
输入:intersectVal = 8,
listA = [4,1,8,4,5],
listB = [5,0,1,8,4,5],
skipA = 2, skipB = 3
 
输出:Reference of the node with value = https://www.isolves.com/it/cxkf/sf/2020-10-19/8
 
输入解释:相交节点的值为 8 (注意 , 如果两个列表相交则不能为 0) 。从各自的表头开始算起 , 链表 A 为 [4,1,8,4,5] , 链表 B
为 [5,0,1,8,4,5] 。在 A 中 , 相交节点前有 2 个节点;在 B 中 , 相交节点前有 3 个节点 。
 
【找出两个链表的第一个公共节点】示例 2:
找出两个链表的第一个公共节点

文章插图
 
输入:intersectVal = 2,
listA = [0,9,1,2,4],
listB = [3,2,4],
skipA = 3, skipB = 1
 
输出:Reference of the node with value = https://www.isolves.com/it/cxkf/sf/2020-10-19/2
 
输入解释:相交节点的值为 2 (注意 , 如果两个列表相交则不能为 0) 。从各自的表头开始算起 , 链表 A 为 [0,9,1,2,4] , 链表 B
为 [3,2,4] 。在 A 中 , 相交节点前有 3 个节点;在 B 中 , 相交节点前有 1 个节点 。
 
示例 3:
找出两个链表的第一个公共节点

文章插图
 
输入:intersectVal = 0,
listA = [2,6,4],
listB = [1,5],
skipA = 3, skipB = 2
 
输出:null
 
输入解释:从各自的表头开始算起 , 链表 A 为 [2,6,4] , 链表 B 为 [1,5] 。由于这两个链表不相交 , 所以 intersectVal
必须为 0 , 而 skipA 和 skipB 可以是任意值 。
解释:这两个链表不相交 , 因此返回 null 。
 
注意:
  1. 如果两个链表没有交点 , 返回 null.
  2. 在返回结果后 , 两个链表仍须保持原有的结构 。
  3. 可假定整个链表结构中没有循环 。
  4. 程序尽量满足 O(n) 时间复杂度 , 且仅用 O(1) 内存 。
 
通过集合set解决
上面说了一大堆 , 其实就是判断两个链表是否相交 , 如果相交就返回他们的相交的交点 , 如果不相交就返回null 。
做这题最容易想到的一种解决方式就是先把第一个链表的节点全部存放到集合set中 , 然后遍历第二个链表的每一个节点 , 判断在集合set中是否存在 , 如果存在就直接返回这个存在的结点 。如果遍历完了 , 在集合set中还没找到 , 说明他们没有相交 , 直接返回null即可 , 原理比较简单 , 直接看下代码
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {//创建集合setSet<ListNode> set = new HashSet<>();//先把链表A的结点全部存放到集合set中while (headA != null) {set.add(headA);headA = headA.next;}//然后访问链表B的结点 , 判断集合中是否包含链表B的结点 , 如果包含就直接返回while (headB != null) {if (set.contains(headB))return headB;headB = headB.next;}//如果集合set不包含链表B的任何一个结点 , 说明他们没有交点 , 直接返回nullreturn null;}123456789101112131415161718 
先统计两个链表的长度
还可以先统计两个链表的长度 , 如果两个链表的长度不一样 , 就让链表长的先走 , 直到两个链表长度一样 , 这个时候两个链表再同时每次往后移一步 , 看节点是否一样 , 如果有相等的 , 说明这个相等的节点就是两链表的交点 , 否则如果走完了还没有找到相等的节点 , 说明他们没有交点 , 直接返回null即可 , 来画个图看一下 。
找出两个链表的第一个公共节点

文章插图
 
最后再来看下代码
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {//统计链表A和链表B的长度int lenA = length(headA), lenB = length(headB);//如果节点长度不一样 , 节点多的先走 , 直到他们的长度一样为止while (lenA != lenB) {if (lenA > lenB) {//如果链表A长 , 那么链表A先走headA = headA.next;lenA--;} else {//如果链表B长 , 那么链表B先走headB = headB.next;lenB--;}}//然后开始比较 , 如果他俩不相等就一直往下走while (headA != headB) {headA = headA.next;headB = headB.next;}//走到最后 , 最终会有两种可能 , 一种是headA为空 , //也就是说他们俩不相交 。还有一种可能就是headA//不为空 , 也就是说headA就是他们的交点return headA;}//统计链表的长度private int length(ListNode node) {int length = 0;while (node != null) {node = node.next;length++;}return length;}


推荐阅读