zoukankan      html  css  js  c++  java
  • 【剑指Offer-代码的鲁棒性】编程题23:链表中环的入口节点

    题目描述

    给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。

    思路1

    首先要判断链表中有没有环:可以利用两个指针,初始都在head,一个指针移动的比较快(一次移动两个节点),另一个指针移动的比较慢(一次移动一个节点),如果两个节点最终相遇了,则说明链表中存在环;如果快指针的下一个节点为nullptr,则说明链表无环。如果链表有环,则快指针和慢指针相遇的节点一定在环中,从相遇节点移动n次可以再次到达相遇节点,则n就是环的长度。此时,再设置两个指针p1和p2,将指针p1先移动n步,然后再同时移动p1,p2,则p1,p2的相遇点就是环的入口。代码如下:

    /*
    struct ListNode {
        int val;
        struct ListNode *next;
        ListNode(int x) :
            val(x), next(NULL) {
        }
    };
    */
    class Solution {
    public:
        ListNode* EntryNodeOfLoop(ListNode* pHead)
        {
            if(pHead==nullptr)
                return nullptr;
            
            ListNode* meetingNode = getMeetingNode(pHead);
            if(meetingNode==nullptr)
                return nullptr;
            int nodeNumsInLoop = 1;    //环中的节点个数
            ListNode* temp = meetingNode->next;
            while(temp!=meetingNode)
            {
                temp = temp->next;
                nodeNumsInLoop++;
            }
            
            ListNode* pSlow = pHead;
            ListNode* pFast = pHead;
            for(int i=0; i<nodeNumsInLoop; i++)
                pFast = pFast->next;
            while(pSlow!=pFast)
            {
                pSlow = pSlow->next;
                pFast = pFast->next;
            }
            return pFast;
        }
        
        ListNode* getMeetingNode(ListNode* pHead)    //寻找环中的相遇点
        {
            ListNode* pFast = pHead;
            ListNode* pSlow = pHead;
            while(pFast->next!=nullptr)
            {
                if(pFast->next!=nullptr && pFast->next->next!=nullptr)
                    pFast = pFast->next->next;
                if(pSlow->next!=nullptr)
                    pSlow = pSlow->next;
                if(pSlow==pFast)
                    return pFast;
            }
            return nullptr;
        }
    };
    

    思路2

    首先判断环是否存在还是和思路 1 类似,使用快慢指针,慢指针每次走一步,快指针每次走两步,如果最终快慢指针相等,则说明有环。否则,如果快指针 fast->next==nullptr,则说明无环。若有环,则将慢指针 slow 回退到链表头,快指针位置不变,也就是相遇的位置,然后快慢指针每次都走一步,如果快慢指针相遇,则相遇点一定是入口。代码如下:

    /*
    struct ListNode {
        int val;
        struct ListNode *next;
        ListNode(int x) :
            val(x), next(NULL) {
        }
    };
    */
    class Solution {
    public:
        ListNode* EntryNodeOfLoop(ListNode* pHead)
        {
            if(pHead==nullptr) return nullptr;
            
            ListNode* slow = pHead;
            ListNode* fast = pHead;
            while(slow!=nullptr && fast->next!=nullptr){
                slow = slow->next;
                fast = fast->next->next;
                if(slow==fast) break;
            }
            if(fast->next==nullptr) return nullptr; // 无环
            
            slow = pHead;
            while(slow!=fast){
                slow = slow->next;
                fast = fast->next;
            }
            return slow;
        }
    };
    
  • 相关阅读:
    OSI参考模型(转)
    H3C交换机配置常用命令(转)
    H3C交换机配置学习随笔
    [Swust OJ 247]--皇帝的新衣(组合数+Lucas定理)
    [Swust OJ 1084]--Mzx0821月赛系列之情书(双线程dp)
    [Swust OJ 404]--最小代价树(动态规划)
    [Swust OJ 610]--吉祥数
    [Swust OJ 137]--波浪数(hash+波浪数构造)
    [Swust OJ 566]--开N方数(牛顿切线法解高次方程)
    [Swust OJ 1125]--又见GCD(数论,素数表存贮因子)
  • 原文地址:https://www.cnblogs.com/flix/p/12449944.html
Copyright © 2011-2022 走看看