死磕算法系列文章
“Leetcode : https://leetcode-cn.com/problems/liang-ge-lian-biao-de-di-yi-ge-gong-gong-jie-dian-lcof/
“GitHub : https://github.com/nateshao/leetcode/blob/main/algo-notes/src/main/java/com/nateshao/sword_offer/topic_39_getIntersectionNode/Solution.java
“题目描述 :输入两个链表,找出它们的第一个公共节点。 难度:简单
“如下面的两个链表:
在节点 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 = 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 = 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。
设「[第一个公共节点」为 node
,「链表 headA
」的节点数量为 a ,「链表 headB
」的节点数为b , 「两链表的公共尾部」的节点数量为 c ,则有:
headA
到 node
前,共有 a - c 个节点;headB
到 node
前,共有 b - c 个节点;考虑构建两个节点指针 A
, B
分别指向两链表头节点 headA
, headB
,做如下操作:
A
先遍历完链表headA
,再开始遍历链表 headB
,当走到 node
时,共走步数为:a+(b−c)B
先遍历完链表 headB
,再开始遍历链表 headA
,当走到 node
时,共走步数为:b+(a−c)如下式所示,此时指针 A
, B
重合,并有两种情况:a+(b−c)=b+(a−c)
A
, B
同时指向「第一个公共节点」node
。A
, B
同时指向 null 。因此返回 A
即可。
复杂度分析:
package com.nateshao.sword_offer.topic_39_getIntersectionNode;
/**
* @date Created by 邵桐杰 on 2022/1/1 23:45
* @微信公众号 千羽的编程时光
* @个人网站 www.nateshao.cn
* @博客 https://nateshao.gitee.io
* @GitHub https://github.com/nateshao
* @Gitee https://gitee.com/nateshao
* Description:
*/
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
ListNode A = headA, B = headB;
while (A != B) {
A = A != null ? A.next : headB;
B = B != null ? B.next : headA;
}
return A;
}
public class ListNode {
int val;
ListNode next;
ListNode(int x) {
val = x;
next = null;
}
}
}
判断两个链表是否相交,可以使用哈希集合存储链表节点。首先遍历链表headA
,并将链表headA
中的每个节点加入哈希集合中。然后遍历链表headB
,对于遍历到的 每个节点,判断该节点是否在哈希集合中:
如果链表headB
中的所有节点都不在哈希集合中,则两个链表不相交,返回null
。
/**
* 哈希集合
* @param headA
* @param headB
* @return
*/
public ListNode getIntersectionNode2(ListNode headA, ListNode headB) {
Set<ListNode> visited = new HashSet<>();
ListNode temp = headA;
while (temp!=null){
visited.add(temp);
temp = temp.next;
}
temp = headB;
while (headB!=null){
if (visited.contains(temp))return temp;
temp=temp.next;
}
return null;
}
复杂度分析
参考链接: