筷子与饺子
Published on 2019-11-11 04:08 in 暂未分类 with 筷子与饺子

面试题 02.08. 环路检测(返回环路开头节点)

面试题 02.08. 环路检测

给定一个链表,如果它是有环链表,实现一个算法返回环路的开头节点。
有环链表的定义:在链表中某个节点的next元素指向在它前面出现过的节点,则表明该链表存在环路。

示例 1:

输入:head = [3,2,0,-4], pos = 1
输出:tail connects to node index 1
解释:链表中有一个环,其尾部连接到第二个节点。

示例 2:

输入:head = [1,2], pos = 0
输出:tail connects to node index 0
解释:链表中有一个环,其尾部连接到第一个节点。

示例 3:

输入:head = [1], pos = -1
输出:no cycle
解释:链表中没有环。

进阶:
你是否可以不用额外空间解决此题?

思路一 利用哈希表

/**
 * 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(head == NULL || head->next ==NULL)
            return NULL;
        unordered_set<ListNode*> seen;
        while(head!=NULL)
        {
            if(seen.count(head))
                return head;
            seen.insert(head);
            head = head->next;
        }
        return NULL;
    }
};

思路二 利用快慢指针(数学问题)

//如果链表有环,请找到环的入口点
//fast一次走两步,slow一次走一步。所以,相遇的时候,fast所走的路程是slow所走的路程的两倍
//设起始位置到环入口点的距离为X,入口点到第一次相遇的位置的距离为L,C代表环的长度。
//slow和fast第一次相遇时,slow:X+L;   fast:X+L+NC (N指代圈次)。
// 由上推出:  2(X+L) = X+L+NC  ->  X = NC - L;和圈数(环数)无关  -> X = C - L;
// 由上可得:当slow和fast第一次相遇时,把slow放到链表头部,与fast一起走,直到再次相遇,
// 那么这个相遇点就是环的入口点。
public class Solution {
    public ListNode detectCycle(ListNode head) {
        ListNode fast = head;
        ListNode slow = head;
    
        while (fast != null && fast.next != null) {
            slow = slow.next;
            fast = fast.next.next;
            if (fast == slow) {
                while (fast != head) {
                    fast = fast.next;
                    head = head.next;
                }
                return head;//改善在此处
            }
        }
        return null;
    }
}

链接

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/linked-list-cycle-lcci

posted @ 2020-10-09 15:00  筷子与饺子  阅读(112)  评论(0编辑  收藏  举报