題目大意:在時間複雜度O(m+n),空間複雜度O(1)的條件下找到兩個鏈表的相交結點
分析:暴力的時間複雜度爲O(mn),肯定不可取。最初的思路是用哈希表記錄已遍歷的結點。但是空間複雜度爲O(m)或O(n)。
方法:雙指針。p和q分別從headA和headB開始遍歷,當p到尾結點(空)時,p返回指向headB;當q到尾結點(空)時,q返回指向headA。當循環遍歷中p和q相遇時即爲相交結點。因爲兩鏈表如果有相交,就意味着尾結點一定相同,假設重疊部分結點c個,不重疊部分分別a、b個,則p和q走過的路程可表示爲:a->c->b=b->c->a。所以可以採用雙指針到達尾結點重返另一鏈表頭結點的方式,來找到相交結點。
代碼:
雙指針
/**
* 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 == NULL || headB == NULL) return NULL;
ListNode* p = headA;
ListNode* q = headB;
while(p != q){
p = p->next;
q = q->next;
if(p == NULL && q == NULL) return NULL;
if(p == NULL) p = headB;
if(q == NULL) q = headA;
}
return p;
}
};
哈希表
/**
* 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 == NULL || headB == NULL) return NULL;
unordered_set<ListNode*> s;
ListNode* p = headA;
ListNode* q = headB;
while(p || q){
if(p){
if(s.find(p) != s.end()) return p;
s.insert(p);
p = p->next;
}
if(q){
if(s.find(q) != s.end()) return q;
s.insert(q);
q = q->next;
}
}
return NULL;
}
};