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

相關文章
相關標籤/搜索