leetcode142——Linked List CycleⅡ

题目大意:找出链表入环的第一个节点,无环返回NULL

分析:

方法一:哈希表记录访问过的结点,leetcode141也可以采用这种方法,但是空间复杂度为O(n)。

方法二:Floyd算法。第一步:先利用快慢指针判断是否有环,并拿到快慢指针相遇的结点。

第二步:然后一个指针p从head出发,一个指针q从相遇结点出发,两者的相遇结点就是入环结点。

第二步证明:假设head到入环节点为n步

当slow走到入环结点时,fast在环中走了n步,还剩b步再次走到入环节点

此时slow走b步,还剩n步;fast也就走了2b步(走完了之前剩下的b步,并且重新从入环节点出发了b步),此时slow和fast相遇

由上可知,slow和fast的相遇结点距离入环节点还有n步,所以当p和q相遇时就是入环节点(因为都走了n步)

代码:

方法一:哈希表

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        unordered_set s;
        ListNode* node = head;
        while(node){
            if(s.count(node)) return node;
            else s.insert(node);
            node = node->next;
        }
        return NULL;
    }
};

方法二:floyd算法

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* getIntersect(ListNode *head){
        ListNode* fast = head;
        ListNode* slow = head;
        while(fast && fast->next){
            fast = fast->next->next;
            slow = slow->next;
            if(fast == slow) return fast;
        }
        return NULL;
    }
    ListNode *detectCycle(ListNode *head) {
        ListNode* intersect = getIntersect(head);
        if(intersect == NULL) return NULL;
        ListNode* p = head;
        ListNode* q = intersect;
        while(p != q){
            p = p->next;
            q = q->next;
        }
        return p;
    }
};

 

你可能感兴趣的:(数据结构-链表)