1、描述
52输入两个链表,找出它们的第一个公共节点。
面试题0207
2、关键字
链表,找相同
3、思路
注意:是第一个公共子节点:相交后面的都相等了。
而不是节点的val值相等的节点,
题目链接
1、双指针:两个走过自己的路,再走对方的路,如果有相同节点,则会两个都走了L1 + L2 - C的节点个数时候相遇,如果没有相同节点:1、如果两个节点个数相同,会在第一次各自都走到最后时候返回NULL,2、如果两个节点个数不同,则会两个都走完两个的时候结束,返回NULL.
2、set查找,先把第一个链表存起来,然后再遍历第二个链表,如果找到就返回,
3、两层循环作比较,就是不知道为啥节点可以直接比较,而用节点的val值作比较还会出错!!!
4、notes
两个结点不断的去对方的轨迹中寻找对方的身影,只要二人有交集,就终会相遇❤
如何快速判断两个链表有没有相交?
如果相交有一个特性:最后一个肯定是相同的,所以直接遍历到两个链表的最后,看是否相等。
5、复杂度
双指针:时间:O(N+M) 都走了L1+L2-C的距离
空间:O(1)
set容器:时间:O(M+N)
空间:O(N):得把一个链表的东西存起来
两层循环:时间:O(N*M)
空间:O(1)
6、code
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 * first=headA;
ListNode * second=headB;
//while((first->val)!=(second->val))
while(first!=second)
{
//first= first->next!=NULL?first->next:headB; // 这个会无限循环下去,时间超限
first=first!=NULL?first->next:headB;
second=second!=NULL?second->next:headA;
}
return first;
}
};
2、缓存set,存起来第一个链表,遍历第二个寻找
/**
* 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; // 特判
set<ListNode*>se; // 把第一个链表用set存起来,然后,再遍历第二个链表,寻找相同的节点,如果有就返回,
ListNode * first=headA;
ListNode * second=headB;
while(first){
se.insert(first);
first=first->next;
}
while(second){
if(se.find(second)!=se.end()) // 在end之前找到了,
return second;
second=second->next;
}
return NULL;
}
};
3、两层循环
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
if(!headA||!headB) return NULL;
auto first=headA;
//auto second=headB;
while(first)
{
auto second=headB;
while(second)
{
if(first->val==second->val)
{
return second;
}
second=second->next;
}
first=first->next;
}
return NULL;
}
};