leetcode q14一、q142有感(Linked List Cycle I 、 II )

LeetCode Q141 Linked List Cycle

Given a linked list, determine if it has a cycle in it. To represent a cycle in the given linked list, we use an integer pos which represents the position (0-indexed) in the linked list where tail connects to.node

If pos is -1, then there is no cycle in the linked list.git

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
复制代码

1思路 & 解法

1.1 思路一:每走过一步留下脚印👣,以后碰见脚印,输出有cycle;

代码以下:github

bool hasCycle(struct ListNode *head) {
    int impossibleNum = INT_MIN + 55467;
    while (head != NULL) {
        if (head->val == impossibleNum) {
            return true;
        }
        head->val = impossibleNum;
        head = head->next;
    }
    return false;
}
复制代码

1.1.1 思路一扩展:显然上述代码有个弊端,修改了原链表;如何不修改原列表去记录脚印👣?

思路参考,用字典,用ListNode的address做为key,每走一个ListNode判断该node的address是否在字典内,若是链表走到底则没有cycle,不然则有cycle(且第一个遇到的为cycle的head)bash

因为c的标准库没有dictionary(reference),此处代码略ide

1.2 思路二:快慢指针,重叠之后证实有cycle

思路二解释:从head node开始,一个指针一次走一个node,另外一个一次走两个node,,若是二者可以相遇,则证实有cycleoop

常识来想很简单,两我的在操场跑步,一我的跑的速度是另外一我的的2倍,他们初始位置不限制;但慢的人跑一圈,快的会跑两圈,他们确定会在某处相遇ui

证实:idea

问题能够等价为:对于cycle里任意两个node(节点),一个以1倍速同方向走,一个以2倍速同方向走,最终必定相遇;
设cycle长为l(l>0),k为两node初始距离(-l < k < l)
问题可视为 2x % l = (x + k) % l ,在 x > 0 状况下必定有解
即 2x = x + k + m * l (m可谓任意正整数) 在 x > 0 状况下有解
显然,
当k < 0时,令m = 1, 即x = l + k;为其中一个解, 
当k >= 0 时,x = k, 为其中一个解;
复制代码

代码:spa

bool hasCycle(struct ListNode *head) {
    if (head == NULL) {
        return false;
    }
    struct ListNode *pSlow = head;
    struct ListNode *pFast = head;
    while (pSlow->next != NULL && pFast->next != NULL && pFast->next->next != NULL) {
        pSlow = pSlow->next;
        pFast = pFast->next->next;
        if (pSlow == pFast) {
            return true;
        }
    }
    return false;
}
复制代码

LeetCode Q142 Linked List Cycle II

Given a linked list, return the node where the cycle begins. If there is no cycle, return null.指针

To represent a cycle in the given linked list, we use an integer pos which represents the position (0-indexed) in the linked list where tail connects to. If pos is -1, then there is no cycle in the linked list.

Note: Do not modify the linked list.

Follow-up: Can you solve it without using extra space?

思路 & 解法

考虑到Do not modify the linked listCan you solve it without using extra space?,q141思路一不适用,考虑q141思路二上作文章;

可是,如何拿到cycle的headnode?

设cycle前node集为pre,pre长度为p,cycle长为l,相遇节点为cycle的第k个node,相遇时慢指针pSlow走的步数为total。
则有: 
①2total = p + k + m * l (m ∈ Z) 
②total = p + k + n * l (n < m, n 属于 Z)
① - ②得 ③total = (m - n) * l 
可得p + k = (m - 2n) * l
复制代码

p + k 是 l的倍数,如何使用该条件获得loopHead?

咱们知道,当咱们快慢指针相遇时,咱们当前的节点位置为k,那么让慢指针k再走p个节点,必定为loopHead节点。
但如何走一个p节点?
brilliant idea:再让一个慢指针从head节点走,两指针第一次相遇,则二者走了p节点!且该节点就是要求的cycle的headnode!!!
复制代码

参考图:

代码:

struct ListNode *detectCycle(struct ListNode *head) {
    if (head == NULL) {
        return head;
    }
    struct ListNode *pSlow = head;
    struct ListNode *pFast = head;
    bool isCycle = false;
    while (pSlow->next != NULL && pFast->next != NULL && pFast->next->next != NULL) {
        pSlow = pSlow->next;
        pFast = pFast->next->next;
        if (pSlow == pFast) {
            isCycle = true;
            break;
        }
    }
    if (isCycle) {
        pFast = head;
        while (pFast != pSlow) {
            pFast = pFast->next;
            pSlow = pSlow->next;
        }
        return pFast;
    }
    return NULL;
}
复制代码

project

相关文章
相关标签/搜索