数据结构面试 之 单链表是否有环及环入口点 附有最详细明了的图解

1.限制与要求

  • 不容许修改链表结构。算法

  • 时间复杂度O(n),空间复杂度O(1)。spa

2.思考

2.1判断是否有环

若是链表有环,那么在遍历链表时则会陷入死循环,利用这个特征,咱们能够设计这样的算法。设计

  • 使用一个slow指针,一个fast指针。指针

  • slow指针一次日后遍历以1个节点,fast指针一次日后遍历2个节点,一直作这样的操做。code

  • 若是fast指针在遍历过程当中,遍历到了NULL节点说明链表没有环。ip

  • 不然当slow指针和falst指针相同,则说明环有节点。leetcode

2.2环的入口节点

咱们假定链表头到环入口的距离是len,环入口到slow和fast交汇点的距离为x,环的长度为R。slow和fast第一次交汇时,设slow走的长度为:d = len + x,而fast走的长度为:2d = len + nR + x,(n >= 1),从而咱们能够得知:2len + 2x = len + nR + x,即len = nR - x,(n >= 1),因而咱们能够获得这样的算法。rem

  • 使用一个cur指针指向链表头节点,一个inter指针指向第一次的交汇点。get

  • cur指针和inter指针一块儿日后遍历。it

  • cur指针和inter指针相等时,cur和inter指针指向的就是环的入口节点。


inter指针在遍历过程当中可能屡次(n >= 1)通过环入口节点,但当cur指针第一次达到入口节点时,inter指针此时必然也指向入口节点。

3.代码实现

/**
 * 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) {
        if (NULL == head) return NULL;
        ListNode * fast = head;
        ListNode * slow = head;
        
        while (1)
        {
            fast = fast->next ? fast->next : NULL;
            if (NULL == fast) break;
            
            fast = fast->next ? fast->next : NULL;
            if (NULL == fast) break;
            
            slow = slow->next;
    
            if (slow == fast) break;
        }
        
        if (NULL == fast) return NULL;
        
        ListNode * cur = head;
        ListNode * inter = slow;
        
        while (cur != inter)
        {
            cur = cur->next;
            inter = inter->next;
        }
        
        return cur;
    }
};

4.OJ练习

LeetCode 单链表是否有环及入口

相关文章
相关标签/搜索