如果两个链表相交,那么相交点之后的长度是相同的。
A和B两个链表长度可能不同,但是A+B和B+A的长度是相同的,所以遍历A+B和遍历B+A一定同时结束。
如果A、B相交的话A和B有一段末尾的子链表是相同的,所以两个遍历的指针一定会同时到达交点。如果A、B不相交的话两个指针就会同时到达A+B(B+A)的尾节点(NULL),此时p == q,跳出循环。
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
if(!headA && !headB) return NULL;
auto p = headA, q = headB;
while(p != q){
p = p == NULL ? headB : p->next;//p == NULL代表走到了末尾
q = q == NULL ? headA : q->next;
}
return p;
}
};
这样的话就是线性时间复杂度和常数空间复杂度。
如果不要求空间复杂度的话,使用哈希表就可以:遍历第一个链表存入哈希表;然后遍历第二个链表,检查第二个链表中的每个元素是否在哈希表中存在即可。
另一个方法,使用长度进行判断。
如果两个单链表有共同的节点,那么从第一个共同节点开始,后面的节点都会重叠,直到链表结束。
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
if(!headA && !headB) return NULL;
int n = 0, m = 0;
for(auto p = headA; p != NULL; p = p->next) ++n;
for(auto p = headB; p != NULL; p = p->next) ++m;
auto p = headA, q = headB;
if(n > m){
for(int i = 0; i < n - m; ++i) p = p->next;//先走两者长度的差值
while(p != q){
if(p) p = p->next;
if(q) q = q->next;
}
}else{
for(int i = 0; i < m - n; ++i) q = q->next;
while(p != q){
if(p) p = p->next;
if(q) q = q->next;
}
}
return p;
}
};