[leetcode Linked List Cycle II] 从生活细节得到的解题思路

附上原题:

给定一个链表,如果该链表存在环路,要求返回环路的开始节点,否则返回NULL。第一个版本只要求判断链表是否存在环路,而这道题在这基础上又增加了难度。

记得上初中的时候,学校开运动会,其中有一项是三千米跑步,这对运动员们的耐力是巨大的考验。经常会出现这样一种情况,跑的快的同学从后面又追上了跑得慢的同学,也就是说,跑的快的那位同学比慢的那位整整快了一圈。

不知道大家有没有从这个故事当中收到启发,操作本身就是一个环路,才使得快得同学可以重新追上慢的同学,如果操场是直线,那根本就不可能追上。重新回到我们的问题上,要判断链表是否存在环路,我是不是可以定义两个指针,第一个指针每次走1歩,第二个指针每次走两步,如果第二个指针与第一个指针又重新相遇,那我们认为存在环路;否则当第二个指针最终指向了NULL,则不存在。这是第一问的解,仔细思考应该不难。

我们来直接观察下面这幅图:


链表的总长度为8,环路的长度为5。我们先让指针P2向前走了5歩,也就是链表的长度,然后P1还是指向第一个节点。我们发现当P2跟P1同时往前再走3歩,它们相遇的节点刚好是环路的开始节点,这难道是巧合?我们来分析下,假设链表的长度为k,环路的长度为d,那么剩余的节点长度为k-d。当P2从头节点向前走了k歩以后,此时它距离最后一个节点的位置还有k-d-1歩,如果它再走一步,就达到了环路的起始位置。再来看P1,P1距离环路的开始节点刚好相差k-d歩,证毕。

那现在的问题是如何获得环路的长度呢?这个其实不难,运用两个指针,第一个指针每次走两步,第二个指针每次走一步,等到他们相遇后,记录他们相遇的节点。然后继续往前,直到再次到达相遇节点,此时走过的路程就为环路的长度。分析完成后,我们用代码将它实现。

class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        int cycleLen = caculateCycleDistance(head);
        if (cycleLen == 0) {
            return NULL;
        }
        ListNode *first = head;
        ListNode *second = head;
       //第一个指针向前走的步数等于环路的长度
        while (cycleLen != 0) {
            second = second->next;
            cycleLen--;
        }
        //两个指针同时向前,相遇后的节点即为环路的开始节点
        while (first != second) {
            first = first->next;
            second = second->next;
        }
        return first;
    }

   /**
    * 计算环路的长度,若不存在环路,返回0
    */
    int caculateCycleDistance(ListNode *head) {
        int cycleLen = 0;

        ListNode *first = head;
        if (!first) {
            return cycleLen;
        }
        ListNode *second = head->next;
        //一个指针每次走一步,另一个指针每次走两步
        //注意每次移动指针的过程中,都要判断是否为NULL
        while (first && second && first != second) {
            first = first->next;
            second = second->next;
            if (!second)
                return cycleLen;
            second = second->next;
        }
        if (first && second) {
            ListNode *meetNode = first; //记录两个指针相遇的节点
            do {
                first = first->next;
                cycleLen++;
            } while (first != meetNode);
        }
        return cycleLen;
    }
};

算法一旦分析完成后,实现起来并不难。唯一需要注意的是,每次移动指针的时候,记得判断指针是否为空。写这段程序的时候,写完第一次提交竟然就直接Accepted了,出乎我的意料。看来这段时间的leetcode没有白刷。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容