160. 相交链表
思路:
这里有一个点必须要清楚,Listnode这个结构体。那么当两个节点相交时,每个链表里的这个节点以及后面的节点是完全一样的,这个“完全一样”包括val,和next所指的节点。在这之前有val相同的节点,但next不相同,所以并不能作为相交的节点。那么根据这个性质,我们只需要存入一个链表到一个查找为O(1)的数据结构,那么我们在遍历另一个链表,只要找到第一个完全一样的节点,我们就可以return 这个节点作为第一个相交的节点了。
如果想不到 完全一样这个点,只注意到了val,那还是比较难有思路的。
/**
* 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) {
unordered_set<ListNode*> st;
ListNode* cur = headA;
while(cur){
st.insert(cur);
cur=cur->next;
}
cur = headB;
while(cur){
if(st.count(cur)) return cur;
cur=cur->next;
}
return cur;
}
};
另一种方法太妙了。
我们假设链表a长度为n,链表b长度为m,链表a不相交的部分为na,链表b不相交部分为mb,相交部分为c,那么n=na+c,m=mb+c,
我们使用两个指针,pa和pb分别指向链表a和链表b并且同时移动,当na!=mb,pa和pb不会同步,那么就不会同时指到相交节点,当pa和pb直到null时,就让 pa指向链表b头节点,pb指向链表a头结点,然后继续同时移动,因为有pa移动了 na+c+mb,pb移动了 mb+c+na,此时,pa和pb移动了相同的次数,那么此时就能指到同一个节点,并且该节点为交叉点,因为两指针交换了,pa在链表b走了mb指向了交叉点,pb走了na指向了交叉点,所以此方法能找到。如果没有交差点,当走完pa走完mb时就为null,pb同时走完na指向null此时 返回null即可。
/**
* 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) {
ListNode* pa = headA;
ListNode* pb = headB;
while(pa!=pb){
pa==NULL? pa=headB:pa=pa->next;
pb==NULL? pb=headA:pb=pb->next;
}
return pb;
}
};