方法一:哈希表
遍历链表a并将每个结点的地址/引用存储在哈希表中。然后检查链表b中的每一个结点是否在哈希表中。若在,则该结点为相交结点。
复杂度分析
时间复杂度 : O(m+n)
空间复杂度 : O(m)或 O(n)
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
set<ListNode*> s;
ListNode* p=headA;
while(p){ //遍历链表a,将每个结点放入set
s.insert(p);
p=p->next;
}
p=headB;
while(p){ //遍历链表b,查看每个结点是否在set中,存在则返回
if(s.find(p)!=s.end())
return p;
p=p->next;
}
return NULL; //不存在返回空
}
};
方法二:双指针
创建两个指针 pA 和 pB,分别初始化为链表和a和b的头结点。然后让它们向后逐结点遍历。
当pA 到达链表的尾部时,将它重定位到链表 B 的头结点; 类似的,当 pB到达链表的尾部时,将它重定位到链表 A 的头结点。
若在某一时刻 pA和 pB相遇,则 pA/pB为相交结点
复杂度分析
时间复杂度 : O(m+n)
空间复杂度 : O(1)
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
if(!headA || !headB) return NULL;
ListNode* pa=headA;
ListNode* pb=headB;
while(pa!=pb){
pa=pa!=NULL?pa->next:headB;
pb=pb!=NULL?pb->next:headA;
}
return pa;
}
};
当短链表a的遍历完时跳到长的链表b开始遍历,两个指针的差为短链表的长度。当长的链表遍历完时跳到短的链表开始遍历,此时他们距离结尾NULL的距离相同,都为短链表的长度。如果它们的话就相交,否则不相交。