题目大意:在时间复杂度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;
}
};