快慢指針的應(yīng)用

快慢指針

快慢指針中的快慢指的是移動(dòng)的步長(zhǎng)矾缓,快慢分別指的是快指針每次移動(dòng)兩步稻爬,滿指針每次移動(dòng)一步

快慢指針的應(yīng)用

·判斷單鏈表是否存在環(huán)

判斷是否存在環(huán)的最好方法就是讓快指針和慢指針同時(shí)從頭開始遍歷整個(gè)鏈表桅锄,如果是環(huán)的話样眠,慢指針一定會(huì)在某一時(shí)刻追上快指針,反之則不然辫秧;或者快指針到達(dá)了NULL被丧,那么也能說明該單鏈表是不存在環(huán)的,代碼如下:

bool isCircle(Node *p)
{
    if(head == nullptr)
        return false;
    Node *slow = head;
    Node *fast = head;
    while(fast != nullptr && fast->next != nullptr)
    {
        slow = slow->next;
        fast = fast->next->next;
        if(slow == fast)
            return true;
    }
    return false;
}

這樣我們就可以實(shí)現(xiàn)一個(gè)對(duì)單鏈表是否有環(huán)的判斷

·在有序鏈表中尋找中位數(shù)

因?yàn)榭熘羔樖锹羔樀亩妒辆浚虼丝熘羔樤诘竭_(dá)終點(diǎn)的時(shí)候蝇摸,慢指針正好指向中點(diǎn)的位置。

同時(shí)我們還要考慮鏈表結(jié)點(diǎn)個(gè)數(shù)的奇偶數(shù)貌夕,當(dāng)快指針移動(dòng)x次后到達(dá)表尾啡专,說明鏈表有奇數(shù)個(gè)(2x+1)結(jié)點(diǎn),直接返回慢指針指向的數(shù)據(jù)即可辱揭。
如果快指針是倒數(shù)第二個(gè)結(jié)點(diǎn)病附,說明鏈表結(jié)點(diǎn)個(gè)數(shù)是偶數(shù),這時(shí)可以根據(jù)“規(guī)則”返回上中位數(shù)或下中位數(shù)或(上中位數(shù)+下中位數(shù))的一半域庇。

具體代碼如下:

while(fast && slow)
{
    if(fast->next == nullptr)
        return slow->data;
    else if(fast->next != nullptr && fast->next->next==nullptr)
        return (slow->data + slow->data)/2;
    else{
        slow = slow->next;
        fast = fast->next->next;
    }
}

·輸出鏈表中的倒數(shù)第k個(gè)節(jié)點(diǎn)

可以定義兩個(gè)指針听皿,第一個(gè)指針從鏈表的頭指針開始遍歷向前走k-1步宽档,第二個(gè)指針保持不動(dòng);從第K步開始又厉,第二個(gè)指針也開始從鏈表的頭指針開始遍歷椎瘟。由于兩個(gè)指針的距離保持在k-1肺蔚,當(dāng)?shù)谝粋€(gè)指針到達(dá)鏈表的尾節(jié)點(diǎn)時(shí)候,第二個(gè)指針正好是倒數(shù)第K個(gè)節(jié)點(diǎn)璧诵。

具體實(shí)現(xiàn)如下:

ListNode *GetNode(ListNode *p, int k)
{
    if(k == 0 || p == nullptr)
        return NULL;
    ListNode *fast = p;
    ListNode *slow = p;
    for(int i = 0; i < k-1; i++)
    {
        fast = fast->next;
        if(fast == nullptr) return NULL;
    }
    while(fast -> next != nullptr)
    {
        slow = slow->next;
        fast = fast->next;
    }
    return slow;
}

這是主要的幾種應(yīng)用段只,之所以要寫出這幾種寫法赞枕,一方面是介紹快慢指針坪创,另一方面是提出下面的幾道在leetcode上見到的題都是用快慢指針來解決問題的姐赡。

快慢指針的習(xí)題參考

143. Reorder List

首先项滑,第一題是143. Reorder List
Given a singly linked list L: L0→L1→…→Ln-1→Ln,
reorder it to: L0→Ln→L1→Ln-1→L2→Ln-2→…

You may not modify the values in the list's nodes, only nodes itself may be changed.

Example 1:
Given 1->2->3->4, reorder it to 1->4->2->3.

Example 2:
Given 1->2->3->4->5, reorder it to 1->5->2->4->3.

我們這道題就可以借助快慢指針進(jìn)行解決:
先用快慢指針將整個(gè)鏈表一分為二,在將第二個(gè)子鏈表進(jìn)行倒序求解危喉,最后合并的到最終的結(jié)果:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    void reorderList(ListNode* head) {
        if(head ==NULL || head->next == NULL ||head->next->next == NULL)
            return;
        ListNode *fast,*slow,*head1,*head2,*post,*cur,*tmp = NULL;
        fast = slow = head;
        while(fast->next && fast->next->next)
        {
            fast = fast->next->next;
            slow = slow->next;
        }
        head1 = head;
        head2 = cur = slow->next;
        slow->next = nullptr;
        //將第二部分鏈表反轉(zhuǎn)
        post = head2->next;
        cur->next = NULL;
        while(post!=NULL)
        {
            tmp = post->next;
            post->next = cur;
            cur = post;
            post = tmp;
        }
        head2 = cur;
        //將第二部分插入到第一部分
        ListNode *cur1 = head1;
        ListNode *cur2 = head2;
        while(cur2!=NULL)
        {
            tmp = cur1->next;
            cur1->next = cur2;
            post = cur2->next;
            cur2->next = tmp;
            cur1 = tmp;
            cur2 = post;
        }
    }
};

第一部分就是使用的快慢指針進(jìn)行的運(yùn)算,通過移動(dòng)指針严蓖,最后fast指針指向終點(diǎn)颗胡,而slow指向中點(diǎn),通過這個(gè)中點(diǎn)哑蔫,可以將整條鏈表分為兩部分手素,之后就可以對(duì)這兩部分進(jìn)行操作了瘩蚪。

第二部分就是對(duì)剛才分出來的鏈表的后半部分進(jìn)行逆轉(zhuǎn)操作疹瘦,比如我們?cè)仁茿->B->C的鏈表,我們要變成C->B->A邓嘹,我們可以看出來汹押,要發(fā)生逆轉(zhuǎn)的話起便,順序是發(fā)生改變的,那么意味著我們需要三個(gè)指針來進(jìn)行調(diào)整妙痹,分別是當(dāng)前節(jié)cur怯伊,以及前一個(gè)節(jié)點(diǎn)pre耿芹,和后一個(gè)節(jié)點(diǎn)nextnode,實(shí)現(xiàn)如下:

ListNode *Reverse(ListNode *p)
{
    ListNode *cur = p;
    ListNode *pre = nullptr;
    ListNode *reverseHead = nullptr;
    while(cur)
    {
        ListNode *nextnode = cur->next;
        if(nextnode == nullptr)
            reverseHead = cur;
        cur->next = pre;
        
        pre = cur;
        cur = nextnode;
    }
}

最后一部分就是實(shí)現(xiàn)鏈表的插入即可媚送,即按照題目中的要求將兩個(gè)鏈表一次插入即可。

234. Palindrome Linked List

第二題是234. Palindrome Linked List
Given a singly linked list, determine if it is a palindrome.

Example 1:
Input: 1->2
Output: false

Example 2:
Input: 1->2->2->1
Output: true
Follow up:
Could you do it in O(n) time and O(1) space?

這道題除了讓判斷是否為回文塘偎,還對(duì)時(shí)間復(fù)雜度和空間復(fù)雜度進(jìn)行了限制吟秩,因此我們可以聯(lián)想到之前所說的快慢指針將整個(gè)鏈表分為兩部分涵防,之后再將后面的鏈表進(jìn)行反轉(zhuǎn)沪铭,再進(jìn)行比較即可杀怠。
具體步驟就不詳細(xì)說明了,把代碼貼出來僅供參考

    ListNode *reverseList(ListNode *head)
    {
        ListNode *pre = nullptr;
        ListNode *next = nullptr;
        while(head != nullptr)
        {
            next = head->next;
            head->next = pre;
            pre = head;
            head = next;
        }
        return pre;
    }
    bool isPalindrome(ListNode* head){
        if(head == nullptr || head->next == nullptr)
            return true;
        ListNode *fast = head;
        ListNode *slow = head;
        while(fast->next != nullptr && fast->next->next != nullptr)
        {
            slow = slow->next;
            fast = fast->next->next;
        }
        slow->next = reverseList(slow->next);
        slow = slow->next;
        while(slow)
        {
            if(slow->val != head->val)
                return false;
            slow = slow->next;
            head = head->next;
        }
        return true;
    }

以上就是對(duì)于快慢指針的學(xué)習(xí)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末硕旗,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子创译,更是在濱河造成了極大的恐慌软族,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,919評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件吱肌,死亡現(xiàn)場(chǎng)離奇詭異仰禽,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)吐葵,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,567評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門温峭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來凤藏,“玉大人揖庄,你說我怎么就攤上這事蹄梢。” “怎么了而咆?”我有些...
    開封第一講書人閱讀 163,316評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)馍驯。 經(jīng)常有香客問我玛痊,道長(zhǎng)狂打,這世上最難降的妖魔是什么趴乡? 我笑而不...
    開封第一講書人閱讀 58,294評(píng)論 1 292
  • 正文 為了忘掉前任蒿涎,我火速辦了婚禮劳秋,結(jié)果婚禮上玻淑,老公的妹妹穿的比我還像新娘补履。我一直安慰自己箫锤,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,318評(píng)論 6 390
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著溺职,像睡著了一般浪耘。 火紅的嫁衣襯著肌膚如雪七冲。 梳的紋絲不亂的頭發(fā)上澜躺,一...
    開封第一講書人閱讀 51,245評(píng)論 1 299
  • 那天掘鄙,我揣著相機(jī)與錄音操漠,去河邊找鬼浊伙。 笑死嚣鄙,一個(gè)胖子當(dāng)著我的面吹牛哑子,可吹牛的內(nèi)容都是我干的赵抢。 我是一名探鬼主播烦却,決...
    沈念sama閱讀 40,120評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼冒冬,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼简烤!你這毒婦竟也來了横侦?” 一聲冷哼從身側(cè)響起枉侧,我...
    開封第一講書人閱讀 38,964評(píng)論 0 275
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎翼虫,沒想到半個(gè)月后珍剑,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體次慢,經(jīng)...
    沈念sama閱讀 45,376評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,592評(píng)論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了由缆。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片均唉。...
    茶點(diǎn)故事閱讀 39,764評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖层扶,靈堂內(nèi)的尸體忽然破棺而出镜会,到底是詐尸還是另有隱情戳表,我是刑警寧澤匾旭,帶...
    沈念sama閱讀 35,460評(píng)論 5 344
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響泞遗,放射性物質(zhì)發(fā)生泄漏史辙。R本人自食惡果不足惜聊倔,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,070評(píng)論 3 327
  • 文/蒙蒙 一见妒、第九天 我趴在偏房一處隱蔽的房頂上張望须揣。 院中可真熱鬧,春花似錦卵酪、人聲如沸凛澎。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,697評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽冷尉。三九已至雀哨,卻和暖如春雾棺,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背尸饺。 一陣腳步聲響...
    開封第一講書人閱讀 32,846評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工螟碎, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留倍谜,地道東北人尔崔。 一個(gè)月前我還...
    沈念sama閱讀 47,819評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像耘拇,于是被迫代替她去往敵國(guó)和親惫叛。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,665評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 鏈表刪除[203] Remove Linked List Elements[19] Remove Nth Node...
    野狗子嗷嗷嗷閱讀 6,290評(píng)論 4 35
  • LeetCode 刷題隨手記 - 第一部分 前 256 題(非會(huì)員)警医,僅算法題,的吐槽 https://leetc...
    蕾娜漢默閱讀 17,764評(píng)論 2 36
  • 搞懂單鏈表常見面試題 Hello 繼上次的 搞懂基本排序算法路星,這個(gè)一星期,我總結(jié)了挥等,我所學(xué)習(xí)和思考的單鏈表基礎(chǔ)知識(shí)...
    醒著的碼者閱讀 4,585評(píng)論 1 45
  • 我有很多朋友郭宝,其中有陳依卓榄檬,陳依卓是我從大班是都是好朋友鹿榜,我們是這樣成為好朋友的:我們?cè)谏洗蟀嗟臅r(shí)候舱殿,我...
    怡迪閱讀 709評(píng)論 0 0
  • 雖然我也不知道迷郑,回學(xué)校要做什么嗡害,但是就是數(shù)著這些日子過的霸妹。又?jǐn)嗑W(wǎng)了十电,笑話和手機(jī)里的歌都是舊的,笑話不怎么好笑叹螟。 實(shí)...
    林三文閱讀 199評(píng)論 0 0