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;
    }
};
posted @ 2021-06-04 20:31  Mrsdwang  阅读(56)  评论(0编辑  收藏  举报