• 链表中环的入口结点


    链表中环的入口结点

    题目描述

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

    第一步两个节点, 一快一慢, 若有环则相遇

    当快慢节点相遇时, 慢结点走了x个节点, 快结点恰巧走了2x个节点, 2x = k*n + x, k为1, 2,..., 此时令其中一个节点等于头结点, 然后以相同速度移动两个节点, 相遇时恰好为环的入口节点

    class Solution {
    public:
        ListNode* EntryNodeOfLoop(ListNode* pHead)
        {
            if ((nullptr == pHead) || (nullptr == pHead->next)) {
                return nullptr;
            }
            ListNode *pNode1 = pHead;
            ListNode *pNode2 = pHead;
            
            while ((nullptr != pNode2) && (nullptr != pNode2->next)) {
                pNode1 = pNode1->next;
                pNode2 = pNode2->next->next;
                
                if (pNode1 == pNode2) {
                    pNode2 = pHead;
                    while (pNode1 != pNode2) {
                        pNode1 = pNode1->next;
                        pNode2 = pNode2->next;
                    }
                    return pNode1;
                }
            }
            return nullptr;
        }
    };
    

    利用快慢节点确定有无环若有则返回相交节点, 否则返回nullptr

    然后利用相交节点确定环的中节点的个数N

    再让一个节点指向头结点, 一个指针指向距头结点第N个节点, 然后以相同速度同时移动两个节点, 相遇时即为环的入口点

    class Solution {
    public:
        // 利用快慢节点移动速度不同, 若有环, 快慢节点必相遇
        ListNode *MeetingNode(ListNode* pHead) {
            if (nullptr == pHead) {
                return nullptr;
            }
            
            ListNode *pSlow = pHead->next;
            if (nullptr == pSlow) {    // 若只有两个节点则不能组成环
                return nullptr;
            }
            
            ListNode *pFast = pSlow->next;
            
            while((nullptr != pSlow) && (nullptr != pFast)) {
                if (pSlow == pFast) {
                    return pSlow;
                }
                pSlow = pSlow->next;
                //pFast = pSlow->next;    // 没有判断pFast移动后是否是空节点
                pFast = pFast->next;    // 需要判断pFast是不是空节点
                if (nullptr != pFast) {
                    pFast = pFast->next;
                }
            }
            
            return nullptr;
        }
        
        ListNode* EntryNodeOfLoop(ListNode* pHead)
        {
            ListNode *meetingNode = MeetingNode(pHead);
            if (nullptr == meetingNode) {
                return nullptr;
            }
            
            // 得到环节点的数目
            ListNode *ct = meetingNode;
            int counts = 1;
            while (ct->next != meetingNode) {
                counts++;
                ct = ct->next;
            }
            
            // 确定环的入口
            ListNode *pNode1 = pHead;    // pNode1指向头结点
            ListNode *pNode2 = pHead;    // pNode2先移动counts节点数目
            for (int i = 0; i < counts; i++) {
                pNode2 = pNode2->next;
            }
            while (pNode1 != pNode2) {
                pNode1 = pNode1->next;
                pNode2 = pNode2->next;
            }
            
            return pNode1;
        }
    };
    
    /*
    struct ListNode {
        int val;
        struct ListNode *next;
        ListNode(int x) :
            val(x), next(NULL) {
        }
    };
    */
    
  • 相关阅读:
    PHP面试总结
    yii2-dingtalk 钉钉群机器人
    分布式锁机制原理及实现方式
    strtotime的一个使用问题
    JavaScript的程序构成
    libsvm源码凝视+算法描写叙述:svm_train
    android事件分发(二)
    Windows 上通过本地搭建 Jekyll环境
    重点:用户画像
    easyui英文提示变中文
  • 原文地址:https://www.cnblogs.com/hesper/p/10504838.html
Copyright © 2020-2023  润新知