方法1:遍历A链表并加入集合中,然后遍历B链表,查看集合是否包含当前节点,有则是相交点,否则不相交
/*
* 相交链表
*/
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
if (headA == null || headB == null) {
return null;
}
Set<ListNode> list = new HashSet<ListNode>();
ListNode currNode = headA;
//遍历A链表
while(currNode.next!= null) {
list.add(currNode);
currNode = currNode.next;
}
//遍历B链表
currNode = headB;
while(currNode.next != null) {
if(list.contains(currNode)) {
return currNode;
}
else {
currNode = currNode.next;
}
}
return null;
}
方法2:双指针,直接照搬力扣解答吧,还是能够比较容易看得懂的
*创建两个指针 pApA 和 pBpB,分别初始化为链表 A 和 B 的头结点。然后让它们向后逐结点遍历。
*当 pApA 到达链表的尾部时,将它重定位到链表 B 的头结点 (你没看错,就是链表 B); 类似的,当 pBpB 到达链表的尾部时,将它重定位到链表 A 的头结点。
*若在某一时刻 pApA 和 pBpB 相遇,则 pApA/pBpB 为相交结点。
*想弄清楚为什么这样可行, 可以考虑以下两个链表: A={1,3,5,7,9,11} 和 B={2,4,9,11},相交于结点 9。 由于 B.length (=4) < A.length (=6),pBpB 比 pApA 少经过 22 个结点,会先到达尾部。将 pBpB 重定向到 A 的头结点,pApA 重定向到 B 的头结点后,pBpB 要比 pApA 多走 2 个结点。因此,它们会同时到达交点。
*如果两个链表存在相交,它们末尾的结点必然相同。因此当 pApA/pBpB 到达链表结尾时,记录下链表 A/B 对应的元素。若最后元素不相同,则两个链表不相交。
复杂度分析
时间复杂度 : O(m+n)O(m+n)。
空间复杂度 : O(1)O(1)。
作者:LeetCode
链接:https://leetcode-cn.com/problems/intersection-of-two-linked-lists/solution/xiang-jiao-lian-biao-by-leetcode/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
ListNode up = headA;
ListNode down = headB;
while(up != down){
if(up == null)
up = headB;
else {
up = up.next;
}
if(down == null )
down = headA;
else
down = down.next;
}
return up;
还有个思想一样,代码很优雅的老哥写的
输入的skipA /skipB 表示之前的节点即使值一样,但是 是new 在堆上的 地址会不一样,而后续节点是通过引用进行连接的链表;
=》所以题目可以表述为在两个链表中找到共有的 引用链表的头结点;
相当于都遍历了 A+B,最后同时达到末尾退出,即 null == null(找不到的情况),N = null,如下
[4,1,8,4,5]N,5,0,1,8,4,5
[5,0,1,8,4,5]N,4,1,8,4,5
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
ListNode p = headA, q = headB;
while(p != q){
p = (p == null) ? headB : p.next;
q = (q == null) ? headA : q.next;
}
return p;
}
}
来源:https://leetcode-cn.com/u/huai-sen-sheng/