最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C語言?推理證明帶環(huán)鏈表詳細(xì)過程

 更新時間:2022年04月09日 09:25:57   作者:yy_上上謙  
單鏈表中同樣也有具有挑戰(zhàn)性的題目,鏈表的帶環(huán)問題可以說是眾多難題中的佼佼者,在這里可能更看重的是邏輯推理和證明的過程

什么是帶環(huán)鏈表:

帶環(huán)鏈表是鏈表最后一個結(jié)點(diǎn)的指針域不是指向空指針,而是指向鏈表之前的結(jié)點(diǎn),這樣就形成了環(huán)狀的鏈表結(jié)構(gòu)。

如圖所示:

判斷鏈表是否帶環(huán):

那么問題來了,如何判斷一個鏈表是否帶環(huán)呢?

這里我們再次運(yùn)用了快慢指針,但是快慢指針又該如何具體設(shè)置呢?

  • 判斷思路:

先定義一個快指針fast,一個慢指針slow。

快指針一定是比慢指針先進(jìn)環(huán)的,當(dāng)slow進(jìn)環(huán)時,fast指針便開始了追slow指針,當(dāng)快指針和慢指針相遇的時候,快指針便追上了慢指針,此時就可以判斷該鏈表是有環(huán)的,但凡快指針指向空就說明該鏈表是不帶環(huán)的。

  • 那么快慢指針一次各走幾步最合適呢?

假設(shè)slow剛進(jìn)環(huán)時,fast與slow之間的距離為N,環(huán)的長度為C。

  • 這里我們要多組討論一下:(先討論有代表的兩組)

1.slow一次走1步,fast一次走2步一定能追上嗎?

2.slow一次走1步,fast一次走3步一定能追上嗎?

…………………

圖為當(dāng)slow剛進(jìn)環(huán)時,假設(shè)fast所在的位置:

1.slow一次走1步,fast一次走2步一定能追上嗎?

每次追擊,fast與slow之間的距離就縮小1,當(dāng)距離N縮小為0的時候,便追上了。

N - 1,N - 2,N - 3,……,0

所以這種情況一定能追上。

2.slow一次走1步,fast一次走3步一定能追上嗎?

每次追擊,fast與slow之間的距離就縮小2,這里要對N進(jìn)行討論:

(1)當(dāng)N為偶數(shù)時,N每次縮小2,當(dāng)距離N縮小為0的時候,便追上了。

         N - 2,N - 4,N - 6,……,0

(2)當(dāng)N為奇數(shù)時,N每次縮小2,當(dāng)距離N縮小為1的時候,下次追擊二者距離扔縮小2,此時               fast就會超過slow,距離N變?yōu)?-1 ,也就是C - 1,這時又要對C  - 1進(jìn)行討論。

  • 當(dāng)C - 1為偶數(shù)時就能追上。 
  • 當(dāng)C - 1為奇數(shù)時就扔會錯過,N再次變成C - 1,那么就會永遠(yuǎn)錯過也就永遠(yuǎn)追不上。

所以這種情況不一定能追上,有可能永遠(yuǎn)追不上。 

3.slow一次走1步,fast一次走4步一定能追上嗎? 

每次追擊,fast與slow之間的距離就縮小3,這里又要對N進(jìn)行討論:

(1)當(dāng)N為3的倍數(shù)時,N每次縮小3,當(dāng)距離N縮小為0的時候,便追上了。

         N - 3,N - 6,N - 9,……,0

(2)當(dāng)N不為3的倍數(shù)時,那么fast會與slow錯過,至于錯過時fast超過slow多少距離還需討論               (超過的距離取決于一開始N的長度)。

  • 當(dāng)追上后,fast超過slow距離為1時,此時fast追slow追擊距離為N即(C - 1),此時又要對C - 1進(jìn)行上述討論,即C - 1是否為3的倍數(shù)的討論。 
  • 當(dāng)追上后,fast超過slow距離為2時,此時fast追slow追擊距離為N即(C - 2),此時又要對C - 2進(jìn)行上述討論,即C - 2是否為3的倍數(shù)的討論。

 所以這種情況只有當(dāng)N為3的倍數(shù)的時候才能追得上。

綜上:能不能追得上取決于兩個指針之間的距離N和環(huán)的大小C。

下面提供一個結(jié)論個人小結(jié):(僅供參考,可能存在局限性)

只要快慢指針的速度差是2的時候,就可能會出現(xiàn)永遠(yuǎn)追不上的問題。假設(shè)fast與slow的速度差為x,那么fast追趕slow一次,他們之間的距離就減少x,途中有可能剛好追上,也有可能錯過。當(dāng)錯過的時候,fast在slow前面,這時fast超過slow的距離的取值只可能是在[1 ~ (x - 1)]之間(x取整數(shù))。同時任意一個正整數(shù),假設(shè)記作m,(m > x)當(dāng)m整除一個整數(shù)x有余數(shù)時,對這個整數(shù)m減去[1 ~ (x - 1)]中任意一個值,總能找到一個值x,使得m - x的值能夠整除x。所以無論環(huán)的長度為多長,假設(shè)環(huán)的長度為C,總有C減去[1 ~ (x - 1)]中任意一個值,使得C - x能夠整除x并且沒余數(shù),既然沒余數(shù)那就是剛好追上的情況。

當(dāng)fast和slow的速度差為2時,即x = 2的時候,C - x,x屬于[1 ~ (x - 1)],那么C - x就只能是C - 1,那么當(dāng)C - 1去整除2的時候,如果C - 1為奇數(shù),那么C - 1整除2必然有余數(shù),并且余數(shù)為1,下次還是C - 1去整除2,還是會余1,所以這時fast就永遠(yuǎn)追不上slow。

總結(jié):

設(shè)置fast一次走2步,slow一次走1步的時候最保險。 因?yàn)榭炻羔樝嗑郚,每追擊一次N就減1,總會減到0,N縮小到0就是追到了。

環(huán)形鏈表 I

環(huán)形鏈表

OJ鏈接

給你一個鏈表的頭節(jié)點(diǎn) head ,判斷鏈表中是否有環(huán)。

如果鏈表中有某個節(jié)點(diǎn),可以通過連續(xù)跟蹤 next 指針再次到達(dá),則鏈表中存在環(huán)。 為了表示給定鏈表中的環(huán),評測系統(tǒng)內(nèi)部使用整數(shù) pos 來表示鏈表尾連接到鏈表中的位置(索引從 0 開始)。注意:pos 不作為參數(shù)進(jìn)行傳遞 。僅僅是為了標(biāo)識鏈表的實(shí)際情況。

如果鏈表中存在環(huán) ,則返回 true 。 否則,返回 false 。

示例 1:

輸入:

head = [3,2,0,-4], pos = 1

輸出:

true

解釋:鏈表中有一個環(huán),其尾部連接到第二個節(jié)點(diǎn)。

示例 2:

輸入:

head = [1,2], pos = 0

輸出:

true

解釋:鏈表中有一個環(huán),其尾部連接到第一個節(jié)點(diǎn)。

示例 3:

輸入:

head = [1], pos = -1

輸出:

false

解釋:鏈表中沒有環(huán)。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
bool hasCycle(struct ListNode *head)
{
    struct ListNode* fast, *slow;
    fast = slow = head;
    while(fast && fast->next)
    {
        fast = fast->next->next;
        slow = slow->next;
        if(slow == fast)
        return true;
    }
 
    return false;
}

思路:

運(yùn)用上述判斷環(huán)形鏈表的結(jié)論,fast一次走2步,slow每次走1步,只要是環(huán)狀就一定會追的到。

找?guī)Лh(huán)形鏈表入環(huán)的第一個結(jié)點(diǎn):

接下來更深層次的問題來了,帶環(huán)鏈表環(huán)的入口該怎么找呢?

以后帶環(huán)問題通常都用fast一次走2步,slow一次走1步。

當(dāng)快指針追到慢指針時,假設(shè)相遇點(diǎn)為meet,slow指針和fast指針在如圖所示的:

注意:

這里快指針一定是先進(jìn)環(huán),slow后進(jìn)環(huán)。

slow指針進(jìn)環(huán)后,在走一圈的時間內(nèi),一定是會被fast追上的 。

 思路:

在是slow指針和fast指針,同時從head頭開始走,直到在meet點(diǎn)相遇,又因?yàn)閒ast指針的速度為slow指針?biāo)俣鹊亩?,那么就一定滿足一個等式關(guān)系:

快指針走的距離 = 慢指針走的距離 * 2

還需討論的是當(dāng)slow進(jìn)環(huán)時,fast在環(huán)內(nèi)走了多久的問題:

  • 當(dāng)L足夠長而C很小時:slow進(jìn)環(huán)時fast可能已經(jīng)在環(huán)內(nèi)走了好多圈了(假設(shè)為n圈)。
  • 當(dāng)L很小而C足夠大時:slow進(jìn)環(huán)時fast可能在環(huán)內(nèi) 連一圈還沒走。

綜合考慮之后再結(jié)合上述等式關(guān)系變得到下列等式:

L + nC + X = 2 * (L+ X) 

化簡得:

L = n * C - X

 這個公式充分說明了,一個指針從head走,一個指針從相遇點(diǎn)meet走,并且每次都走一步,一     直走下去,它們最終會在環(huán)的入口點(diǎn)相遇?。?!

環(huán)形鏈表 II

環(huán)形鏈表 II

OJ鏈接

給定一個鏈表的頭節(jié)點(diǎn)  head ,返回鏈表開始入環(huán)的第一個節(jié)點(diǎn)。 如果鏈表無環(huán),則返回 null。

如果鏈表中有某個節(jié)點(diǎn),可以通過連續(xù)跟蹤 next 指針再次到達(dá),則鏈表中存在環(huán)。 為了表示給定鏈表中的環(huán),評測系統(tǒng)內(nèi)部使用整數(shù) pos 來表示鏈表尾連接到鏈表中的位置(索引從 0 開始)。如果 pos 是 -1,則在該鏈表中沒有環(huán)。注意:pos 不作為參數(shù)進(jìn)行傳遞,僅僅是為了標(biāo)識鏈表的實(shí)際情況。不允許修改 鏈表。

示例 1:

輸入:

head = [3,2,0,-4], pos = 1

輸出:

返回索引為 1 的鏈表節(jié)點(diǎn)

解釋:鏈表中有一個環(huán),其尾部連接到第二個節(jié)點(diǎn)。 示例 2:

輸入:

head = [1,2], pos = 0

輸出:

返回索引為 0 的鏈表節(jié)點(diǎn)

解釋:鏈表中有一個環(huán),其尾部連接到第一個節(jié)點(diǎn)。

示例 3:

輸入:

head = [1], pos = -1

輸出:

返回 null

解釋:鏈表中沒有環(huán)。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode *detectCycle(struct ListNode *head)
{
    struct ListNode* fast, *slow;
    slow = fast = head;
    while(fast && fast->next)
    {
        fast = fast->next->next;
        slow = slow->next;
        if(slow == fast)
        {
            struct ListNode* meet = slow;
            while(head != meet)
            {
                meet = meet->next;
                head = head->next;
            }
            return meet;
        }
    }
    return NULL;
}

思路1: 

先運(yùn)用上述判斷環(huán)形鏈表的結(jié)論找到相遇點(diǎn),再運(yùn)用上述找環(huán)形入口點(diǎn)的結(jié)論,就能輕松找到環(huán)的入口點(diǎn)。

思路2:

先運(yùn)用上述判斷環(huán)形鏈表的結(jié)論找到相遇點(diǎn),再將相遇點(diǎn)斷開,這時就變成了上一篇博客找相交鏈表公共結(jié)點(diǎn)的問題,示意圖如下:

 參考代碼如下:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode *detectCycle(struct ListNode *head)
{
    struct ListNode* fast, *slow;
    slow = fast = head;
    int len1 = 0,len2 = 0;
    while(fast && fast->next)
    {
        fast = fast->next->next;
        slow = slow->next;
        if(slow == fast)
        {
            struct ListNode* shortList, *longList, *meet, *longTail, *shortTail;
            longList = longTail = head;
            meet = shortList = shortTail = slow->next;
            slow->next = NULL;
            while(shortTail)
            {
                shortTail = shortTail->next;
                len1++;
            }
            while(longTail)
            {
                longTail = longTail->next;
                len2++;
            }
            int gap = abs(len1 - len2);
            if(len1 > len2)
            {
                longList = meet;
                shortList = head;
            }       
            while(gap--)
            {
                longList = longList->next;
            }     
            while(shortList != longList)
            {
                longList = longList->next;
                shortList = shortList->next;
            }
            return longList;
        }
    }
    return NULL;
}

到此這篇關(guān)于C語言 推理證明帶環(huán)鏈表詳細(xì)過程的文章就介紹到這了,更多相關(guān)C語言 帶環(huán)鏈表內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C語言數(shù)據(jù)的存儲超詳細(xì)講解上篇

    C語言數(shù)據(jù)的存儲超詳細(xì)講解上篇

    使用編程語言進(jìn)行編程時,需要用到各種變量來存儲各種信息。變量保留的是它所存儲的值的內(nèi)存位置。這意味著,當(dāng)您創(chuàng)建一個變量時,就會在內(nèi)存中保留一些空間。您可能需要存儲各種數(shù)據(jù)類型的信息,操作系統(tǒng)會根據(jù)變量的數(shù)據(jù)類型,來分配內(nèi)存和決定在保留內(nèi)存中存儲什么
    2022-04-04
  • 論C++的lambda是函數(shù)還是對象

    論C++的lambda是函數(shù)還是對象

    這篇文章主要介紹了論C++的lambda是函數(shù)還是對象,對于有捕獲的lambda,其等價于對象。對于沒有任何捕獲的lambda,其等價于函數(shù),下面來看看具體的相關(guān)內(nèi)容,需要的朋友可以參考一下
    2022-02-02
  • PTA刷題C語言編程順序顛倒輸出實(shí)現(xiàn)

    PTA刷題C語言編程順序顛倒輸出實(shí)現(xiàn)

    本篇文章是在刷PTA題目是遇到的一道題,給定一句話,要求將句中所有單詞順序顛倒輸出,本文來帶你解答,有需要的朋友可以借鑒參考下
    2021-09-09
  • C字符串操作函數(shù)的實(shí)現(xiàn)詳細(xì)解析

    C字符串操作函數(shù)的實(shí)現(xiàn)詳細(xì)解析

    以下是對C語言中字符串操作函數(shù)的實(shí)現(xiàn)進(jìn)行了詳細(xì)的分析介紹,需要的朋友可以過來參考下
    2013-08-08
  • Qt?關(guān)于容器的遍歷迭代器的使用問題小結(jié)

    Qt?關(guān)于容器的遍歷迭代器的使用問題小結(jié)

    Qt是一個跨平臺的 C++ 開發(fā)庫,主要用來開發(fā)圖形用戶界面程序,當(dāng)然也可以開發(fā)不帶界面的命令行程序,本文重點(diǎn)給大家介紹Qt?關(guān)于容器的遍歷迭代器的使用問題小結(jié),感興趣的朋友一起看看吧
    2022-03-03
  • C++ 先對數(shù)組排序,在進(jìn)行折半查找

    C++ 先對數(shù)組排序,在進(jìn)行折半查找

    以下小編就為大家介紹兩種實(shí)現(xiàn)方法。第一種方法是,選擇排序法+循環(huán)折半查找法。第二種方法是,冒泡排序法+遞歸折半查找法。需要的朋友可以過來參考下,希望對大家有所幫助
    2013-10-10
  • C++可變參數(shù)模板深入深剖

    C++可變參數(shù)模板深入深剖

    個可變參數(shù)模板(variadic template)就是一個接受可變數(shù)目參數(shù)的函數(shù)模板或類模板,下面這篇文章主要給大家介紹了關(guān)于C++可變參數(shù)模板的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-10-10
  • stl常用算法(Algorithms)介紹(stl排序算法、非變序型隊(duì)列)

    stl常用算法(Algorithms)介紹(stl排序算法、非變序型隊(duì)列)

    這篇文章主要介紹了stl常用算法(Algorithms)介紹(stl排序算法、非變序型隊(duì)列),需要的朋友可以參考下
    2014-05-05
  • C語言中的各種文件讀寫方法小結(jié)

    C語言中的各種文件讀寫方法小結(jié)

    這篇文章主要介紹了C語言中的各種文件讀寫方法小結(jié),是C語言入門學(xué)習(xí)中的基礎(chǔ)知識,需要的朋友可以參考下
    2015-07-07
  • C++多態(tài)的實(shí)現(xiàn)及原理詳細(xì)解析

    C++多態(tài)的實(shí)現(xiàn)及原理詳細(xì)解析

    C++的多態(tài)性用一句話概括就是:在基類的函數(shù)前加上virtual關(guān)鍵字,在派生類中重寫該函數(shù),運(yùn)行時將會根據(jù)對象的實(shí)際類型來調(diào)用相應(yīng)的函數(shù)。如果對象類型是派生類,就調(diào)用派生類的函數(shù);如果對象類型是基類,就調(diào)用基類的函數(shù)
    2013-09-09

最新評論

滦南县| 屯昌县| 甘德县| 福安市| 封丘县| 微山县| 安陆市| 台山市| 怀集县| 湖州市| 肥西县| 宕昌县| 保山市| 商水县| 白山市| 民乐县| 榆林市| 岳阳县| 四子王旗| 屯留县| 陆良县| 苍山县| 平乡县| 洪江市| 阿鲁科尔沁旗| 乐都县| 泰宁县| 报价| 西平县| 苏尼特右旗| 沙雅县| 湘阴县| 屏边| 大悟县| 阿克苏市| 共和县| 大丰市| 永胜县| 新泰市| 海晏县| 崇礼县|