力扣题目链接
思想(数学):设链表A的长度为a,链表B的长度为b,A到交点D的距离为c,B到交点D的距离为d。显然可以得到两者相交链表的长度为:a - c = b - d ,变换一下式子得到:a + d = b + c.
用一个指针从链表A出发,走完后,接着从链表B出发,另一个指针从链表B出发,走完后,接着从链表A出发。若两个链表相交,当前一个指针走了a + d步时,此时后一个指针走b + c步,即走到了交点。若两个链表不相交,两个指针最终都会走向NULL;
总的来说是让双指针,一个指针走一遍A,再走B。另一个指针走一遍B,再走A。当两个指针走第二个链表时相等的点即为交点。若无交点, 两个指针最终都为NULL;
代码
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
ListNode t1 = headA, t2 = headB;
while (t1 != t2) {
t1 = t1 != null ? t1.next : headB;
t2 = t2 != null ? t2.next : headA;
}
return t1;
}
}
思路(非数学):注意本题是找两个链表的交点,即两个节点是相同的,而不是简单的值相等。如果找到交点,那么两个链表后面的节点一定是一样的,因为他们是通过next指针连接起来的。
即如果找到两个链表相等的节点,那么就直接返回这个节点即可,后面的节点就无需再比较了,一定是相等的。
暴力解法是遍历链表A,每遍历一个节点,再遍历链表B看是否有相等的节点,如果有直接返回此节点即可。如果没有继续循环。时间复杂度为0(n*m)
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
ListNode t1 = headA;
while (t1 != null) {
ListNode t2 = headB;
while ( t2 != null) {
if (t1 == t2) return t1;
t2 = t2.next;
}
t1 =t1.next;
}
return null;
}
}
法三:首先遍历两个链表求出长度。然后求出两个链表长度的差值,让长的链表向后走差值步,让两个链表对齐。然后同时两个链表同时向后走,如果有相同的节点即找到交点,直接返回。时间复杂度为O(n + m)
代码
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
ListNode a = headA, b = headB;
int s1 = 0, s2 = 0;
while (a != null){
a = a.next;
s1 ++;
}
while (b != null) {
b = b.next;
s2 ++;
}
a = headA;
b = headB;
if (s2 > s1) {
//交换链表
int temp = s1;
s1 = s2;
s2 =temp;
ListNode tempNode = a;
a = b;
b = tempNode;
}
int gap = s1 - s2;
while (gap -- > 0) { //走到与b同一起点
a = a.next;
}
while (a != null) {
if (a == b) return a;
a = a.next;
b = b.next;
}
return null;
}
}