一、题目
给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。
图示两个链表在节点 c1 开始相交:
题目数据 保证 整个链式结构中不存在环。
注意,函数返回结果后,链表必须 保持其原始结构 。
二、思路
1)获取长度+双指针
观察题目给出的链表,如果进行两个指针移动,怎么知道另一个指针访问过?
由于相交链表的最后一段是共同拥有的,所以从相交节点开始到最末端的长度相等(也就是图中c1、c2、c3),可以采用以下思路:
1、获取A链表长度和B链表长度
2、将A和B的遍历指针对齐(比如B链表需要移动到b2位置),确保到相交节点的位置距离相等
3、同时移动两个遍历指针,判断两个指针指向对象是否是同一个
还有不相交的情况需要考虑,如果两个指针指向了末尾节点都不相等,它们会继续向下指向null,这个判断是相等的,满足题目要求的返回值。
2)哈希表
如果需要快速解题,最简单的思路就是使用哈希表记录A链表的所有节点,然后遍历B链表查询是否存在该节点。
逻辑清晰,代码量少,适合先验证逻辑。但耗时较多。
三、代码
1)获取长度+双指针
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
int lenA = getLength(headA);
int lenB = getLength(headB);
int diff = lenA - lenB;
if (diff > 0) {
while (diff-- > 0) {
headA = headA.next;
}
} else {
while (diff++ < 0) {
headB = headB.next;
}
}
while (headA != headB) {
headA = headA.next;
headB = headB.next;
}
return headA;
}
private int getLength(ListNode head) {
int len = 0;
while (head != null) {
len++;
head = head.next;
}
return len;
}
}
时间复杂度为O(max(lenA, lenB)),空间复杂度为O(1)。
2)哈希表
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
Set<ListNode> set = new HashSet();
while (headA != null) {
set.add(headA);
headA = headA.next;
}
while (headB != null) {
if (set.contains(headB)) {
return headB;
}
headB = headB.next;
}
return headB;
}
}
时间复杂度为O(lenB*log(lenA)),空间复杂度为O(lenA)。