//编写一个程序,找到两个单链表相交的起始节点。//// 如下面的两个链表://////// 在节点 c1 开始相交。//////// 示例 1://////// 输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA = 2, s//kipB = 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。////////// 注意:////// 如果两个链表没有交点,返回 null.// 在返回结果后,两个链表仍须保持原有的结构。// 可假定整个链表结构中没有循环。// 程序尽量满足 O(n) 时间复杂度,且仅用 O(1) 内存。//// Related Topics 链表// 👍 857 👎 0
暴力法
两个链表依次循环比较,找到那个相交的链表。
时间复杂度: 两个链表要循环比较,时间复杂度O(M*N)
代码比较丑陋。
哈希表
将链表A的节点放入哈希表中,循环链表B寻找相等的节点。
时间复杂度:O(M+N)
空间复杂度:O(M). 需要将链表A放入哈希表中。
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
Set<ListNode> set = new HashSet<>();
ListNode point = headA;
while (point != null){
set.add(point);
point = point.next;
}
point = headB;
while (point != null){
if (set.contains(point)){
return point;
}
point = point.next;
}
return null;
}
}
指针遍历
忘记了从哪看到的,链表有环的情况,只要一个快指针一个慢指针,他们重合的时候就是这个链表成环的时候。
这题双指针的问题在于,并不能确定两个链表长度相同,也即重合前的长度不一定相同。如果两个指针同时比较并后移的话,可能出现的情况是,一个已经进入重合部分,一个还没进入。这就错过了重合部分的判断。
解决方法是如果一个链表已经遍历结束,就将该指针指向另一个链表。
这样做的目的是保证两个链表长度相同。遍历A,总遍历长度就是 M+N, 遍历B,总遍历长度是N+M。
假设两个链表是这样,红色部分表示重合。
那么两个链表拼接之后就是这样
可以看到,两个链表即使前面长度不同,但是遍历到之后,依然有着共同的重合部分。
因此链表AB遍历到最后的时候会在相同的位置进入重合部分。
时间复杂度 : O(M+N)
没有使用额外空间。
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
ListNode point1 = headA;
ListNode point2 = headB;
while (point1 != point2){
point1 = point1 == null ? headB : point1.next;
point2 = point2 == null ? headA : point2.next;
}
return point1;
}
}
