zoukankan      html  css  js  c++  java
  • 《剑指offer》第二十三题(链表中环的入口结点)

    // 面试题23:链表中环的入口结点
    // 题目:一个链表中包含环,如何找出环的入口结点?例如,在图3.8的链表中,
    // 环的入口结点是结点3。
    
    #include <iostream>
    #include "List.h"
    
    ListNode* MeetingNode(ListNode* pHead)//鲁棒一:先确定有没有环,有的话先求得环中任意一个节点
    {
        if (pHead == nullptr)//若头结点为空
            return nullptr;
    
        ListNode* pSlow = pHead->m_pNext;
        if (pSlow == nullptr)//若只有一个节点
            return nullptr;
    
        ListNode* pFast = pSlow->m_pNext;
        while (pFast != nullptr && pSlow != nullptr)//判断碰到尾节点后有没有环
        {
            if (pFast == pSlow)
                return pFast;
    
            pSlow = pSlow->m_pNext;
    
            pFast = pFast->m_pNext;
            if (pFast != nullptr)//判断碰到尾节点后有没有环
                pFast = pFast->m_pNext;
        }
    
        return nullptr;
    }
    
    ListNode* EntryNodeOfLoop(ListNode* pHead)//开始计算入口节点,第一步先求环的个数,第二步通过两个前后指针计算入口节点
    {
        ListNode* meetingNode = MeetingNode(pHead);
        if (meetingNode == nullptr)//如果存在环,得到一个环中节点
            return nullptr;
    
        // 得到环中结点的数目
        int nodesInLoop = 1;
        ListNode* pNode1 = meetingNode;
        while (pNode1->m_pNext != meetingNode)
        {
            pNode1 = pNode1->m_pNext;
            ++nodesInLoop;
        }
    
        // 先移动pNode1,次数为环中结点的数目
        pNode1 = pHead;
        for (int i = 0; i < nodesInLoop; ++i)
            pNode1 = pNode1->m_pNext;
    
        // 再移动pNode1和pNode2
        ListNode* pNode2 = pHead;
        while (pNode1 != pNode2)//二者只能相遇在入口处
        {
            pNode1 = pNode1->m_pNext;
            pNode2 = pNode2->m_pNext;
        }
    
        return pNode1;
    }
    
    // ==================== Test Code ====================
    void Test(const char* testName, ListNode* pHead, ListNode* entryNode)
    {
        if (testName != nullptr)
            printf("%s begins: ", testName);
    
        if (EntryNodeOfLoop(pHead) == entryNode)
            printf("Passed.
    ");
        else
            printf("FAILED.
    ");
    }
    
    // A list has a node, without a loop
    void Test1()
    {
        ListNode* pNode1 = CreateListNode(1);
    
        Test("Test1", pNode1, nullptr);
    
        DestroyList(pNode1);
    }
    
    // A list has a node, with a loop
    void Test2()
    {
        ListNode* pNode1 = CreateListNode(1);
        ConnectListNodes(pNode1, pNode1);
    
        Test("Test2", pNode1, pNode1);
    
        delete pNode1;
        pNode1 = nullptr;
    }
    
    // A list has multiple nodes, with a loop 
    void Test3()
    {
        ListNode* pNode1 = CreateListNode(1);
        ListNode* pNode2 = CreateListNode(2);
        ListNode* pNode3 = CreateListNode(3);
        ListNode* pNode4 = CreateListNode(4);
        ListNode* pNode5 = CreateListNode(5);
    
        ConnectListNodes(pNode1, pNode2);
        ConnectListNodes(pNode2, pNode3);
        ConnectListNodes(pNode3, pNode4);
        ConnectListNodes(pNode4, pNode5);
        ConnectListNodes(pNode5, pNode3);
    
        Test("Test3", pNode1, pNode3);
    
        delete pNode1;
        pNode1 = nullptr;
        delete pNode2;
        pNode2 = nullptr;
        delete pNode3;
        pNode3 = nullptr;
        delete pNode4;
        pNode4 = nullptr;
        delete pNode5;
        pNode5 = nullptr;
    }
    
    // A list has multiple nodes, with a loop 
    void Test4()
    {
        ListNode* pNode1 = CreateListNode(1);
        ListNode* pNode2 = CreateListNode(2);
        ListNode* pNode3 = CreateListNode(3);
        ListNode* pNode4 = CreateListNode(4);
        ListNode* pNode5 = CreateListNode(5);
    
        ConnectListNodes(pNode1, pNode2);
        ConnectListNodes(pNode2, pNode3);
        ConnectListNodes(pNode3, pNode4);
        ConnectListNodes(pNode4, pNode5);
        ConnectListNodes(pNode5, pNode1);
    
        Test("Test4", pNode1, pNode1);
    
        delete pNode1;
        pNode1 = nullptr;
        delete pNode2;
        pNode2 = nullptr;
        delete pNode3;
        pNode3 = nullptr;
        delete pNode4;
        pNode4 = nullptr;
        delete pNode5;
        pNode5 = nullptr;
    }
    
    // A list has multiple nodes, with a loop 
    void Test5()
    {
        ListNode* pNode1 = CreateListNode(1);
        ListNode* pNode2 = CreateListNode(2);
        ListNode* pNode3 = CreateListNode(3);
        ListNode* pNode4 = CreateListNode(4);
        ListNode* pNode5 = CreateListNode(5);
    
        ConnectListNodes(pNode1, pNode2);
        ConnectListNodes(pNode2, pNode3);
        ConnectListNodes(pNode3, pNode4);
        ConnectListNodes(pNode4, pNode5);
        ConnectListNodes(pNode5, pNode5);
    
        Test("Test5", pNode1, pNode5);
    
        delete pNode1;
        pNode1 = nullptr;
        delete pNode2;
        pNode2 = nullptr;
        delete pNode3;
        pNode3 = nullptr;
        delete pNode4;
        pNode4 = nullptr;
        delete pNode5;
        pNode5 = nullptr;
    }
    
    // A list has multiple nodes, without a loop 
    void Test6()
    {
        ListNode* pNode1 = CreateListNode(1);
        ListNode* pNode2 = CreateListNode(2);
        ListNode* pNode3 = CreateListNode(3);
        ListNode* pNode4 = CreateListNode(4);
        ListNode* pNode5 = CreateListNode(5);
    
        ConnectListNodes(pNode1, pNode2);
        ConnectListNodes(pNode2, pNode3);
        ConnectListNodes(pNode3, pNode4);
        ConnectListNodes(pNode4, pNode5);
    
        Test("Test6", pNode1, nullptr);
    
        DestroyList(pNode1);
    }
    
    // Empty list
    void Test7()
    {
        Test("Test7", nullptr, nullptr);
    }
    
    int main(int argc, char* argv[])
    {
        Test1();
        Test2();
        Test3();
        Test4();
        Test5();
        Test6();
        Test7();
        system("pause");
        return 0;
    }
  • 相关阅读:
    vuejs中使用echart图表
    锚点链接
    如何动态修改网页的标题(title)?
    如何为图片添加热点链接?(map + area)
    cookie
    如何为你的网站添加标志性的图标(头像)呢?
    图片拖拽上传至服务器
    js定时器之setTimeout的使用
    input[type=file]中使用ajaxSubmit来图片上传
    input[type=file]样式更改以及图片上传预览
  • 原文地址:https://www.cnblogs.com/CJT-blog/p/10488977.html
Copyright © 2011-2022 走看看