链表

扫码查看

目录:

6、【剑指Offer学习】【面试题06:从尾到头打印链表】

18、【剑指Offer学习】【面试题18:在O(1)时间删除链表结点】

22、【剑指Offer学习】【面试题22:链表中倒数第k个结点】

23、【剑指Offer学习】【面试题23:链表中环的入口结点】

24、【剑指Offer学习】【面试题24:反转链表】

25、【剑指Offer学习】【面试题25:合并两个排序的链表】

35、【剑指Offer学习】【面试题35:复杂链表的复制】

36、【剑指Offer学习】【面试题36:二叉搜索树与双向链表】

52、【剑指Offer学习】【面试题52:两个链表的第一个公共结点】

6. 【剑指Offer学习】【面试题06:从尾到头打印链表】

        /*******************************************************************
        Copyright(c) 2016, Harry He
        All rights reserved.

        Distributed under the BSD license.
        (See accompanying file LICENSE.txt at
        https://github.com/zhedahht/CodingInterviewChinese2/blob/master/LICENSE.txt)
        *******************************************************************/

        //==================================================================
        // 《剑指Offer——名企面试官精讲典型编程题》代码
        // 作者:何海涛
        //==================================================================

        // 面试题6:从尾到头打印链表
        // 题目:输入一个链表的头结点,从尾到头反过来打印出每个结点的值。

        #include "..\Utilities\List.h"
        #include <stack>

        void PrintListReversingly_Iteratively(ListNode* pHead)
        {
            std::stack<ListNode*> nodes;

            ListNode* pNode = pHead;
            while(pNode != nullptr)
            {
                nodes.push(pNode);
                pNode = pNode->m_pNext;
            }

            while(!nodes.empty())
            {
                pNode = nodes.top();
                printf("%d\t", pNode->m_nValue);
                nodes.pop();
            }
        }

        void PrintListReversingly_Recursively(ListNode* pHead)
        {
            if(pHead != nullptr)
            {
                if (pHead->m_pNext != nullptr)
                {
                    PrintListReversingly_Recursively(pHead->m_pNext);
                }

                printf("%d\t", pHead->m_nValue);
            }
        }

        // ====================测试代码====================
        void Test(ListNode* pHead)
        {
            PrintList(pHead);
            PrintListReversingly_Iteratively(pHead);
            printf("\n");
            PrintListReversingly_Recursively(pHead);
        }

        // 1->2->3->4->5
        void Test1()
        {
            printf("\nTest1 begins.\n");

            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(pNode1);

            DestroyList(pNode1);
        }

        // 只有一个结点的链表: 1
        void Test2()
        {
            printf("\nTest2 begins.\n");

            ListNode* pNode1 = CreateListNode(1);

            Test(pNode1);

            DestroyList(pNode1);
        }

        // 空链表
        void Test3()
        {
            printf("\nTest3 begins.\n");

            Test(nullptr);
        }

        int main(int argc, char* argv[])
        {
            Test1();
            Test2();
            Test3();

            return 0;
        }
        

18. 面试题18:在O(1)时间删除链表结点

    /*******************************************************************
    Copyright(c) 2016, Harry He
    All rights reserved.

    Distributed under the BSD license.
    (See accompanying file LICENSE.txt at
    https://github.com/zhedahht/CodingInterviewChinese2/blob/master/LICENSE.txt)
    *******************************************************************/

    //==================================================================
    // 《剑指Offer——名企面试官精讲典型编程题》代码
    // 作者:何海涛
    //==================================================================

    // 面试题18(一):在O(1)时间删除链表结点
    // 题目:给定单向链表的头指针和一个结点指针,定义一个函数在O(1)时间删除该
    // 结点。

    #include <cstdio>
    #include "..\Utilities\List.h"

    void DeleteNode(ListNode** pListHead, ListNode* pToBeDeleted)
    {
        if(!pListHead || !pToBeDeleted)
            return;

        // 要删除的结点不是尾结点
        if(pToBeDeleted->m_pNext != nullptr)
        {
            ListNode* pNext = pToBeDeleted->m_pNext;
            pToBeDeleted->m_nValue = pNext->m_nValue;
            pToBeDeleted->m_pNext = pNext->m_pNext;

            delete pNext;
            pNext = nullptr;
        }
        // 链表只有一个结点,删除头结点(也是尾结点)
        else if(*pListHead == pToBeDeleted)
        {
            delete pToBeDeleted;
            pToBeDeleted = nullptr;
            *pListHead = nullptr;
        }
        // 链表中有多个结点,删除尾结点
        else
        {
            ListNode* pNode = *pListHead;
            while(pNode->m_pNext != pToBeDeleted)
            {
                pNode = pNode->m_pNext;
            }

            pNode->m_pNext = nullptr;
            delete pToBeDeleted;
            pToBeDeleted = nullptr;
        }
    }

    // ====================测试代码====================
    void Test(ListNode* pListHead, ListNode* pNode)
    {
        printf("The original list is: \n");
        PrintList(pListHead);

        printf("The node to be deleted is: \n");
        PrintListNode(pNode);

        DeleteNode(&pListHead, pNode);

        printf("The result list is: \n");
        PrintList(pListHead);
    }

    // 链表中有多个结点,删除中间的结点
    void Test1()
    {
        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(pNode1, pNode3);

        DestroyList(pNode1);
    }

    // 链表中有多个结点,删除尾结点
    void Test2()
    {
        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(pNode1, pNode5);

        DestroyList(pNode1);
    }

    // 链表中有多个结点,删除头结点
    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);

        Test(pNode1, pNode1);

        DestroyList(pNode1);
    }

    // 链表中只有一个结点,删除头结点
    void Test4()
    {
        ListNode* pNode1 = CreateListNode(1);

        Test(pNode1, pNode1);
    }

    // 链表为空
    void Test5()
    {
        Test(nullptr, nullptr);
    }

    int main(int argc, char* argv[])
    {
        Test1();
        Test2();
        Test3();
        Test4();
        Test5();

        return 0;
    }

    /*******************************************************************
    Copyright(c) 2016, Harry He
    All rights reserved.

    Distributed under the BSD license.
    (See accompanying file LICENSE.txt at
    https://github.com/zhedahht/CodingInterviewChinese2/blob/master/LICENSE.txt)
    *******************************************************************/

    //==================================================================
    // 《剑指Offer——名企面试官精讲典型编程题》代码
    // 作者:何海涛
    //==================================================================

    // 面试题18(二):删除链表中重复的结点
    // 题目:在一个排序的链表中,如何删除重复的结点?例如,在图3.4(a)中重复
    // 结点被删除之后,链表如图3.4(b)所示。

    #include <cstdio>
    #include "../Utilities/list.h"

    void DeleteDuplication(ListNode** pHead)
    {
        if(pHead == nullptr || *pHead == nullptr)
            return;

        ListNode* pPreNode = nullptr;
        ListNode* pNode = *pHead;
        while(pNode != nullptr)
        {
            ListNode *pNext = pNode->m_pNext;
            bool needDelete = false;
            if(pNext != nullptr && pNext->m_nValue == pNode->m_nValue)
                needDelete = true;

            if(!needDelete)
            {
                pPreNode = pNode;
                pNode = pNode->m_pNext;
            }
            else
            {
                int value = pNode->m_nValue;
                ListNode* pToBeDel = pNode;
                while(pToBeDel != nullptr && pToBeDel->m_nValue == value)
                {
                    pNext = pToBeDel->m_pNext;

                    delete pToBeDel;
                    pToBeDel = nullptr;

                    pToBeDel = pNext;
                }

                if(pPreNode == nullptr)
                    *pHead = pNext;
                else
                    pPreNode->m_pNext = pNext;
                pNode = pNext;
            }
        }
    }

    // ====================测试代码====================
    void Test(char* testName, ListNode** pHead, int* expectedValues, int expectedLength)
    {
        if(testName != nullptr)
            printf("%s begins: ", testName);

        DeleteDuplication(pHead);

        int index = 0;
        ListNode* pNode = *pHead;
        while(pNode != nullptr && index < expectedLength)
        {
            if(pNode->m_nValue != expectedValues[index])
                break;

            pNode = pNode->m_pNext;
            index++;
        }

        if(pNode == nullptr && index == expectedLength)
            printf("Passed.\n");
        else
            printf("FAILED.\n");
    }

    // 某些结点是重复的
    void Test1()
    {
        ListNode* pNode1 = CreateListNode(1);
        ListNode* pNode2 = CreateListNode(2);
        ListNode* pNode3 = CreateListNode(3);
        ListNode* pNode4 = CreateListNode(3);
        ListNode* pNode5 = CreateListNode(4);
        ListNode* pNode6 = CreateListNode(4);
        ListNode* pNode7 = CreateListNode(5);

        ConnectListNodes(pNode1, pNode2);
        ConnectListNodes(pNode2, pNode3);
        ConnectListNodes(pNode3, pNode4);
        ConnectListNodes(pNode4, pNode5);
        ConnectListNodes(pNode5, pNode6);
        ConnectListNodes(pNode6, pNode7);

        ListNode* pHead = pNode1;

        int expectedValues[] = { 1, 2, 5 };
        Test("Test1", &pHead, expectedValues, sizeof(expectedValues) / sizeof(int));

        DestroyList(pHead);
    }

    // 没有重复的结点
    void Test2()
    {
        ListNode* pNode1 = CreateListNode(1);
        ListNode* pNode2 = CreateListNode(2);
        ListNode* pNode3 = CreateListNode(3);
        ListNode* pNode4 = CreateListNode(4);
        ListNode* pNode5 = CreateListNode(5);
        ListNode* pNode6 = CreateListNode(6);
        ListNode* pNode7 = CreateListNode(7);

        ConnectListNodes(pNode1, pNode2);
        ConnectListNodes(pNode2, pNode3);
        ConnectListNodes(pNode3, pNode4);
        ConnectListNodes(pNode4, pNode5);
        ConnectListNodes(pNode5, pNode6);
        ConnectListNodes(pNode6, pNode7);

        ListNode* pHead = pNode1;

        int expectedValues[] = { 1, 2, 3, 4, 5, 6, 7 };
        Test("Test2", &pHead, expectedValues, sizeof(expectedValues) / sizeof(int));

        DestroyList(pHead);
    }

    // 除了一个结点之外其他所有结点的值都相同
    void Test3()
    {
        ListNode* pNode1 = CreateListNode(1);
        ListNode* pNode2 = CreateListNode(1);
        ListNode* pNode3 = CreateListNode(1);
        ListNode* pNode4 = CreateListNode(1);
        ListNode* pNode5 = CreateListNode(1);
        ListNode* pNode6 = CreateListNode(1);
        ListNode* pNode7 = CreateListNode(2);

        ConnectListNodes(pNode1, pNode2);
        ConnectListNodes(pNode2, pNode3);
        ConnectListNodes(pNode3, pNode4);
        ConnectListNodes(pNode4, pNode5);
        ConnectListNodes(pNode5, pNode6);
        ConnectListNodes(pNode6, pNode7);

        ListNode* pHead = pNode1;

        int expectedValues[] = { 2 };
        Test("Test3", &pHead, expectedValues, sizeof(expectedValues) / sizeof(int));

        DestroyList(pHead);
    }

    // 所有结点的值都相同
    void Test4()
    {
        ListNode* pNode1 = CreateListNode(1);
        ListNode* pNode2 = CreateListNode(1);
        ListNode* pNode3 = CreateListNode(1);
        ListNode* pNode4 = CreateListNode(1);
        ListNode* pNode5 = CreateListNode(1);
        ListNode* pNode6 = CreateListNode(1);
        ListNode* pNode7 = CreateListNode(1);

        ConnectListNodes(pNode1, pNode2);
        ConnectListNodes(pNode2, pNode3);
        ConnectListNodes(pNode3, pNode4);
        ConnectListNodes(pNode4, pNode5);
        ConnectListNodes(pNode5, pNode6);
        ConnectListNodes(pNode6, pNode7);

        ListNode* pHead = pNode1;

        Test("Test4", &pHead, nullptr, 0);

        DestroyList(pHead);
    }

    // 所有结点都成对出现
    void Test5()
    {
        ListNode* pNode1 = CreateListNode(1);
        ListNode* pNode2 = CreateListNode(1);
        ListNode* pNode3 = CreateListNode(2);
        ListNode* pNode4 = CreateListNode(2);
        ListNode* pNode5 = CreateListNode(3);
        ListNode* pNode6 = CreateListNode(3);
        ListNode* pNode7 = CreateListNode(4);
        ListNode* pNode8 = CreateListNode(4);

        ConnectListNodes(pNode1, pNode2);
        ConnectListNodes(pNode2, pNode3);
        ConnectListNodes(pNode3, pNode4);
        ConnectListNodes(pNode4, pNode5);
        ConnectListNodes(pNode5, pNode6);
        ConnectListNodes(pNode6, pNode7);
        ConnectListNodes(pNode7, pNode8);

        ListNode* pHead = pNode1;

        Test("Test5", &pHead, nullptr, 0);

        DestroyList(pHead);
    }

    // 除了两个结点之外其他结点都成对出现
    void Test6()
    {
        ListNode* pNode1 = CreateListNode(1);
        ListNode* pNode2 = CreateListNode(1);
        ListNode* pNode3 = CreateListNode(2);
        ListNode* pNode4 = CreateListNode(3);
        ListNode* pNode5 = CreateListNode(3);
        ListNode* pNode6 = CreateListNode(4);
        ListNode* pNode7 = CreateListNode(5);
        ListNode* pNode8 = CreateListNode(5);

        ConnectListNodes(pNode1, pNode2);
        ConnectListNodes(pNode2, pNode3);
        ConnectListNodes(pNode3, pNode4);
        ConnectListNodes(pNode4, pNode5);
        ConnectListNodes(pNode5, pNode6);
        ConnectListNodes(pNode6, pNode7);
        ConnectListNodes(pNode7, pNode8);

        ListNode* pHead = pNode1;

        int expectedValues[] = { 2, 4 };
        Test("Test6", &pHead, expectedValues, sizeof(expectedValues) / sizeof(int));

        DestroyList(pHead);
    }

    // 链表中只有两个不重复的结点
    void Test7()
    {
        ListNode* pNode1 = CreateListNode(1);
        ListNode* pNode2 = CreateListNode(2);

        ConnectListNodes(pNode1, pNode2);

        ListNode* pHead = pNode1;

        int expectedValues[] = { 1, 2 };
        Test("Test7", &pHead, expectedValues, sizeof(expectedValues) / sizeof(int));

        DestroyList(pHead);
    }

    // 结点中只有一个结点
    void Test8()
    {
        ListNode* pNode1 = CreateListNode(1);

        ConnectListNodes(pNode1, nullptr);

        ListNode* pHead = pNode1;

        int expectedValues[] = { 1 };
        Test("Test8", &pHead, expectedValues, sizeof(expectedValues) / sizeof(int));

        DestroyList(pHead);
    }

    // 结点中只有两个重复的结点
    void Test9()
    {
        ListNode* pNode1 = CreateListNode(1);
        ListNode* pNode2 = CreateListNode(1);

        ConnectListNodes(pNode1, pNode2);

        ListNode* pHead = pNode1;

        Test("Test9", &pHead, nullptr, 0);

        DestroyList(pHead);
    }

    // 空链表
    void Test10()
    {
        ListNode* pHead = nullptr;

        Test("Test10", &pHead, nullptr, 0);
    }

    int main(int argc, char* argv[])
    {
        Test1();
        Test2();
        Test3();
        Test4();
        Test5();
        Test6();
        Test7();
        Test8();
        Test9();
        Test10();

        return 0;
    }

22. 面试题22:链表中倒数第k个结点

        /*******************************************************************
        Copyright(c) 2016, Harry He
        All rights reserved.

        Distributed under the BSD license.
        (See accompanying file LICENSE.txt at
        https://github.com/zhedahht/CodingInterviewChinese2/blob/master/LICENSE.txt)
        *******************************************************************/

        //==================================================================
        // 《剑指Offer——名企面试官精讲典型编程题》代码
        // 作者:何海涛
        //==================================================================

        // 面试题22:链表中倒数第k个结点
        // 题目:输入一个链表,输出该链表中倒数第k个结点。为了符合大多数人的习惯,
        // 本题从1开始计数,即链表的尾结点是倒数第1个结点。例如一个链表有6个结点,
        // 从头结点开始它们的值依次是1、2、3、4、5、6。这个链表的倒数第3个结点是
        // 值为4的结点。

        #include <cstdio>
        #include "..\Utilities\List.h"

        ListNode* FindKthToTail(ListNode* pListHead, unsigned int k)
        {
            if(pListHead == nullptr || k == 0)
                return nullptr;

            ListNode *pAhead = pListHead;
            ListNode *pBehind = nullptr;

            for(unsigned int i = 0; i < k - 1; ++ i)
            {
                if(pAhead->m_pNext != nullptr)
                    pAhead = pAhead->m_pNext;
                else
                {
                    return nullptr;
                }
            }

            pBehind = pListHead;
            while(pAhead->m_pNext != nullptr)
            {
                pAhead = pAhead->m_pNext;
                pBehind = pBehind->m_pNext;
            }

            return pBehind;
        }

        // ====================测试代码====================
        // 测试要找的结点在链表中间
        void Test1()
        {
            printf("=====Test1 starts:=====\n");
            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);

            printf("expected result: 4.\n");
            ListNode* pNode = FindKthToTail(pNode1, 2);
            PrintListNode(pNode);

            DestroyList(pNode1);
        }

        // 测试要找的结点是链表的尾结点
        void Test2()
        {
            printf("=====Test2 starts:=====\n");
            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);

            printf("expected result: 5.\n");
            ListNode* pNode = FindKthToTail(pNode1, 1);
            PrintListNode(pNode);

            DestroyList(pNode1);
        }

        // 测试要找的结点是链表的头结点
        void Test3()
        {
            printf("=====Test3 starts:=====\n");
            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);

            printf("expected result: 1.\n");
            ListNode* pNode = FindKthToTail(pNode1, 5);
            PrintListNode(pNode);

            DestroyList(pNode1);
        }

        // 测试空链表
        void Test4()
        {
            printf("=====Test4 starts:=====\n");
            printf("expected result: nullptr.\n");
            ListNode* pNode = FindKthToTail(nullptr, 100);
            PrintListNode(pNode);
        }

        // 测试输入的第二个参数大于链表的结点总数
        void Test5()
        {
            printf("=====Test5 starts:=====\n");
            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);

            printf("expected result: nullptr.\n");
            ListNode* pNode = FindKthToTail(pNode1, 6);
            PrintListNode(pNode);

            DestroyList(pNode1);
        }

        // 测试输入的第二个参数为0
        void Test6()
        {
            printf("=====Test6 starts:=====\n");
            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);

            printf("expected result: nullptr.\n");
            ListNode* pNode = FindKthToTail(pNode1, 0);
            PrintListNode(pNode);

            DestroyList(pNode1);
        }

        int main(int argc, char* argv[])
        {
            Test1();
            Test2();
            Test3();
            Test4();
            Test5();
            Test6();

            return 0;
        }

23. 面试题23:链表中环的入口结点

            /*******************************************************************
            Copyright(c) 2016, Harry He
            All rights reserved.

            Distributed under the BSD license.
            (See accompanying file LICENSE.txt at
            https://github.com/zhedahht/CodingInterviewChinese2/blob/master/LICENSE.txt)
            *******************************************************************/

            //==================================================================
            // 《剑指Offer——名企面试官精讲典型编程题》代码
            // 作者:何海涛
            //==================================================================

            // 面试题23:链表中环的入口结点
            // 题目:一个链表中包含环,如何找出环的入口结点?例如,在图3.8的链表中,
            // 环的入口结点是结点3。

            #include <cstdio>
            #include "../Utilities/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(char* testName, ListNode* pHead, ListNode* entryNode)
            {
                if(testName != nullptr)
                    printf("%s begins: ", testName);

                if(EntryNodeOfLoop(pHead) == entryNode)
                    printf("Passed.\n");
                else
                    printf("FAILED.\n");
            }

            // 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();

                return 0;
            }

24. 面试题24:反转链表

            /*******************************************************************
            Copyright(c) 2016, Harry He
            All rights reserved.

            Distributed under the BSD license.
            (See accompanying file LICENSE.txt at
            https://github.com/zhedahht/CodingInterviewChinese2/blob/master/LICENSE.txt)
            *******************************************************************/

            //==================================================================
            // 《剑指Offer——名企面试官精讲典型编程题》代码
            // 作者:何海涛
            //==================================================================

            // 面试题24:反转链表
            // 题目:定义一个函数,输入一个链表的头结点,反转该链表并输出反转后链表的
            // 头结点。

            #include <cstdio>
            #include "..\Utilities\List.h"

            ListNode* ReverseList(ListNode* pHead)
            {
                ListNode* pReversedHead = nullptr;
                ListNode* pNode = pHead;
                ListNode* pPrev = nullptr;
                while(pNode != nullptr)
                {
                    ListNode* pNext = pNode->m_pNext;

                    if(pNext == nullptr)
                        pReversedHead = pNode;

                    pNode->m_pNext = pPrev;

                    pPrev = pNode;
                    pNode = pNext;
                }

                return pReversedHead;
            }

            // ====================测试代码====================
            ListNode* Test(ListNode* pHead)
            {
                printf("The original list is: \n");
                PrintList(pHead);

                ListNode* pReversedHead = ReverseList(pHead);

                printf("The reversed list is: \n");
                PrintList(pReversedHead);

                return pReversedHead;
            }

            // 输入的链表有多个结点
            void Test1()
            {
                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);

                ListNode* pReversedHead = Test(pNode1);

                DestroyList(pReversedHead);
            }

            // 输入的链表只有一个结点
            void Test2()
            {
                ListNode* pNode1 = CreateListNode(1);

                ListNode* pReversedHead = Test(pNode1);

                DestroyList(pReversedHead);
            }

            // 输入空链表
            void Test3()
            {
                Test(nullptr);
            }

            int main(int argc, char* argv[])
            {
                Test1();
                Test2();
                Test3();

                return 0;
            }

25. 面试题25:合并两个排序的链表

            /*******************************************************************
            Copyright(c) 2016, Harry He
            All rights reserved.

            Distributed under the BSD license.
            (See accompanying file LICENSE.txt at
            https://github.com/zhedahht/CodingInterviewChinese2/blob/master/LICENSE.txt)
            *******************************************************************/

            //==================================================================
            // 《剑指Offer——名企面试官精讲典型编程题》代码
            // 作者:何海涛
            //==================================================================

            // 面试题25:合并两个排序的链表
            // 题目:输入两个递增排序的链表,合并这两个链表并使新链表中的结点仍然是按
            // 照递增排序的。例如输入图3.11中的链表1和链表2,则合并之后的升序链表如链
            // 表3所示。

            #include <cstdio>
            #include "..\Utilities\List.h"

            ListNode* Merge(ListNode* pHead1, ListNode* pHead2)
            {
                if(pHead1 == nullptr)
                    return pHead2;
                else if(pHead2 == nullptr)
                    return pHead1;

                ListNode* pMergedHead = nullptr;

                if(pHead1->m_nValue < pHead2->m_nValue)
                {
                    pMergedHead = pHead1;
                    pMergedHead->m_pNext = Merge(pHead1->m_pNext, pHead2);
                }
                else
                {
                    pMergedHead = pHead2;
                    pMergedHead->m_pNext = Merge(pHead1, pHead2->m_pNext);
                }

                return pMergedHead;
            }

            // ====================测试代码====================
            ListNode* Test(char* testName, ListNode* pHead1, ListNode* pHead2)
            {
                if(testName != nullptr)
                    printf("%s begins:\n", testName);

                printf("The first list is:\n");
                PrintList(pHead1);

                printf("The second list is:\n");
                PrintList(pHead2);

                printf("The merged list is:\n");
                ListNode* pMergedHead = Merge(pHead1, pHead2);
                PrintList(pMergedHead);

                printf("\n\n");

                return pMergedHead;
            }

            // list1: 1->3->5
            // list2: 2->4->6
            void Test1()
            {
                ListNode* pNode1 = CreateListNode(1);
                ListNode* pNode3 = CreateListNode(3);
                ListNode* pNode5 = CreateListNode(5);

                ConnectListNodes(pNode1, pNode3);
                ConnectListNodes(pNode3, pNode5);

                ListNode* pNode2 = CreateListNode(2);
                ListNode* pNode4 = CreateListNode(4);
                ListNode* pNode6 = CreateListNode(6);

                ConnectListNodes(pNode2, pNode4);
                ConnectListNodes(pNode4, pNode6);

                ListNode* pMergedHead = Test("Test1", pNode1, pNode2);

                DestroyList(pMergedHead);
            }

            // 两个链表中有重复的数字
            // list1: 1->3->5
            // list2: 1->3->5
            void Test2()
            {
                ListNode* pNode1 = CreateListNode(1);
                ListNode* pNode3 = CreateListNode(3);
                ListNode* pNode5 = CreateListNode(5);

                ConnectListNodes(pNode1, pNode3);
                ConnectListNodes(pNode3, pNode5);

                ListNode* pNode2 = CreateListNode(1);
                ListNode* pNode4 = CreateListNode(3);
                ListNode* pNode6 = CreateListNode(5);

                ConnectListNodes(pNode2, pNode4);
                ConnectListNodes(pNode4, pNode6);

                ListNode* pMergedHead = Test("Test2", pNode1, pNode2);

                DestroyList(pMergedHead);
            }

            // 两个链表都只有一个数字
            // list1: 1
            // list2: 2
            void Test3()
            {
                ListNode* pNode1 = CreateListNode(1);
                ListNode* pNode2 = CreateListNode(2);

                ListNode* pMergedHead = Test("Test3", pNode1, pNode2);

                DestroyList(pMergedHead);
            }

            // 一个链表为空链表
            // list1: 1->3->5
            // list2: 空链表
            void Test4()
            {
                ListNode* pNode1 = CreateListNode(1);
                ListNode* pNode3 = CreateListNode(3);
                ListNode* pNode5 = CreateListNode(5);

                ConnectListNodes(pNode1, pNode3);
                ConnectListNodes(pNode3, pNode5);

                ListNode* pMergedHead = Test("Test4", pNode1, nullptr);

                DestroyList(pMergedHead);
            }

            // 两个链表都为空链表
            // list1: 空链表
            // list2: 空链表
            void Test5()
            {
                ListNode* pMergedHead = Test("Test5", nullptr, nullptr);
            }

            int main(int argc, char* argv[])
            {
                Test1();
                Test2();
                Test3();
                Test4();
                Test5();

                return 0;
            }

35. 面试题35:复杂链表的复制

            /*******************************************************************
            Copyright(c) 2016, Harry He
            All rights reserved.

            Distributed under the BSD license.
            (See accompanying file LICENSE.txt at
            https://github.com/zhedahht/CodingInterviewChinese2/blob/master/LICENSE.txt)
            *******************************************************************/

            //==================================================================
            // 《剑指Offer——名企面试官精讲典型编程题》代码
            // 作者:何海涛
            //==================================================================

            // 面试题35:复杂链表的复制
            // 题目:请实现函数ComplexListNode* Clone(ComplexListNode* pHead),复
            // 制一个复杂链表。在复杂链表中,每个结点除了有一个m_pNext指针指向下一个
            // 结点外,还有一个m_pSibling 指向链表中的任意结点或者nullptr。

            #include <cstdio>
            #include "ComplexList.h"

            void CloneNodes(ComplexListNode* pHead);
            void ConnectSiblingNodes(ComplexListNode* pHead);
            ComplexListNode* ReconnectNodes(ComplexListNode* pHead);

            ComplexListNode* Clone(ComplexListNode* pHead)
            {
                CloneNodes(pHead);
                ConnectSiblingNodes(pHead);
                return ReconnectNodes(pHead);
            }

            void CloneNodes(ComplexListNode* pHead)
            {
                ComplexListNode* pNode = pHead;
                while(pNode != nullptr)
                {
                    ComplexListNode* pCloned = new ComplexListNode();
                    pCloned->m_nValue = pNode->m_nValue;
                    pCloned->m_pNext = pNode->m_pNext;
                    pCloned->m_pSibling = nullptr;

                    pNode->m_pNext = pCloned;

                    pNode = pCloned->m_pNext;
                }
            }

            void ConnectSiblingNodes(ComplexListNode* pHead)
            {
                ComplexListNode* pNode = pHead;
                while(pNode != nullptr)
                {
                    ComplexListNode* pCloned = pNode->m_pNext;
                    if(pNode->m_pSibling != nullptr)
                    {
                        pCloned->m_pSibling = pNode->m_pSibling->m_pNext;
                    }

                    pNode = pCloned->m_pNext;
                }
            }

            ComplexListNode* ReconnectNodes(ComplexListNode* pHead)
            {
                ComplexListNode* pNode = pHead;
                ComplexListNode* pClonedHead = nullptr;
                ComplexListNode* pClonedNode = nullptr;

                if(pNode != nullptr)
                {
                    pClonedHead = pClonedNode = pNode->m_pNext;
                    pNode->m_pNext = pClonedNode->m_pNext;
                    pNode = pNode->m_pNext;
                }

                while(pNode != nullptr)
                {
                    pClonedNode->m_pNext = pNode->m_pNext;
                    pClonedNode = pClonedNode->m_pNext;

                    pNode->m_pNext = pClonedNode->m_pNext;
                    pNode = pNode->m_pNext;
                }

                return pClonedHead;
            }

            // ====================测试代码====================
            void Test(const char* testName, ComplexListNode* pHead)
            {
                if(testName != nullptr)
                    printf("%s begins:\n", testName);

                printf("The original list is:\n");
                PrintList(pHead);

                ComplexListNode* pClonedHead = Clone(pHead);

                printf("The cloned list is:\n");
                PrintList(pClonedHead);
            }

            //          -----------------
            //         \|/              |
            //  1-------2-------3-------4-------5
            //  |       |      /|\             /|\
            //  --------+--------               |
            //          -------------------------
            void Test1()
            {
                ComplexListNode* pNode1 = CreateNode(1);
                ComplexListNode* pNode2 = CreateNode(2);
                ComplexListNode* pNode3 = CreateNode(3);
                ComplexListNode* pNode4 = CreateNode(4);
                ComplexListNode* pNode5 = CreateNode(5);

                BuildNodes(pNode1, pNode2, pNode3);
                BuildNodes(pNode2, pNode3, pNode5);
                BuildNodes(pNode3, pNode4, nullptr);
                BuildNodes(pNode4, pNode5, pNode2);

                Test("Test1", pNode1);
            }

            // m_pSibling指向结点自身
            //          -----------------
            //         \|/              |
            //  1-------2-------3-------4-------5
            //         |       | /|\           /|\
            //         |       | --             |
            //         |------------------------|
            void Test2()
            {
                ComplexListNode* pNode1 = CreateNode(1);
                ComplexListNode* pNode2 = CreateNode(2);
                ComplexListNode* pNode3 = CreateNode(3);
                ComplexListNode* pNode4 = CreateNode(4);
                ComplexListNode* pNode5 = CreateNode(5);

                BuildNodes(pNode1, pNode2, nullptr);
                BuildNodes(pNode2, pNode3, pNode5);
                BuildNodes(pNode3, pNode4, pNode3);
                BuildNodes(pNode4, pNode5, pNode2);

                Test("Test2", pNode1);
            }

            // m_pSibling形成环
            //          -----------------
            //         \|/              |
            //  1-------2-------3-------4-------5
            //          |              /|\
            //          |               |
            //          |---------------|
            void Test3()
            {
                ComplexListNode* pNode1 = CreateNode(1);
                ComplexListNode* pNode2 = CreateNode(2);
                ComplexListNode* pNode3 = CreateNode(3);
                ComplexListNode* pNode4 = CreateNode(4);
                ComplexListNode* pNode5 = CreateNode(5);

                BuildNodes(pNode1, pNode2, nullptr);
                BuildNodes(pNode2, pNode3, pNode4);
                BuildNodes(pNode3, pNode4, nullptr);
                BuildNodes(pNode4, pNode5, pNode2);

                Test("Test3", pNode1);
            }

            // 只有一个结点
            void Test4()
            {
                ComplexListNode* pNode1 = CreateNode(1);
                BuildNodes(pNode1, nullptr, pNode1);

                Test("Test4", pNode1);
            }

            // 鲁棒性测试
            void Test5()
            {
                Test("Test5", nullptr);
            }

            int main(int argc, char* argv[])
            {
                Test1();
                Test2();
                Test3();
                Test4();
                Test5();

                return 0;
            }

36. 面试题36:二叉搜索树与双向链表

            /*******************************************************************
            Copyright(c) 2016, Harry He
            All rights reserved.

            Distributed under the BSD license.
            (See accompanying file LICENSE.txt at
            https://github.com/zhedahht/CodingInterviewChinese2/blob/master/LICENSE.txt)
            *******************************************************************/

            //==================================================================
            // 《剑指Offer——名企面试官精讲典型编程题》代码
            // 作者:何海涛
            //==================================================================

            // 面试题36:二叉搜索树与双向链表
            // 题目:输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求
            // 不能创建任何新的结点,只能调整树中结点指针的指向。

            #include <cstdio>
            #include "..\Utilities\BinaryTree.h"

            void ConvertNode(BinaryTreeNode* pNode, BinaryTreeNode** pLastNodeInList);

            BinaryTreeNode* Convert(BinaryTreeNode* pRootOfTree)
            {
                BinaryTreeNode *pLastNodeInList = nullptr;
                ConvertNode(pRootOfTree, &pLastNodeInList);

                // pLastNodeInList指向双向链表的尾结点,
                // 我们需要返回头结点
                BinaryTreeNode *pHeadOfList = pLastNodeInList;
                while(pHeadOfList != nullptr && pHeadOfList->m_pLeft != nullptr)
                    pHeadOfList = pHeadOfList->m_pLeft;

                return pHeadOfList;
            }

            void ConvertNode(BinaryTreeNode* pNode, BinaryTreeNode** pLastNodeInList)
            {
                if(pNode == nullptr)
                    return;

                BinaryTreeNode *pCurrent = pNode;

                if (pCurrent->m_pLeft != nullptr)
                    ConvertNode(pCurrent->m_pLeft, pLastNodeInList);

                pCurrent->m_pLeft = *pLastNodeInList;
                if(*pLastNodeInList != nullptr)
                    (*pLastNodeInList)->m_pRight = pCurrent;

                *pLastNodeInList = pCurrent;

                if (pCurrent->m_pRight != nullptr)
                    ConvertNode(pCurrent->m_pRight, pLastNodeInList);
            }

            // ====================测试代码====================
            void PrintDoubleLinkedList(BinaryTreeNode* pHeadOfList)
            {
                BinaryTreeNode* pNode = pHeadOfList;

                printf("The nodes from left to right are:\n");
                while(pNode != nullptr)
                {
                    printf("%d\t", pNode->m_nValue);

                    if(pNode->m_pRight == nullptr)
                        break;
                    pNode = pNode->m_pRight;
                }

                printf("\nThe nodes from right to left are:\n");
                while(pNode != nullptr)
                {
                    printf("%d\t", pNode->m_nValue);

                    if(pNode->m_pLeft == nullptr)
                        break;
                    pNode = pNode->m_pLeft;
                }

                printf("\n");
            }

            void DestroyList(BinaryTreeNode* pHeadOfList)
            {
                BinaryTreeNode* pNode = pHeadOfList;
                while(pNode != nullptr)
                {
                    BinaryTreeNode* pNext = pNode->m_pRight;

                    delete pNode;
                    pNode = pNext;
                }
            }

            void Test(char* testName, BinaryTreeNode* pRootOfTree)
            {
                if(testName != nullptr)
                    printf("%s begins:\n", testName);

                PrintTree(pRootOfTree);

                BinaryTreeNode* pHeadOfList = Convert(pRootOfTree);

                PrintDoubleLinkedList(pHeadOfList);
            }

            //            10
            //         /      \
            //        6        14
            //       /\        /\
            //      4  8     12  16
            void Test1()
            {
                BinaryTreeNode* pNode10 = CreateBinaryTreeNode(10);
                BinaryTreeNode* pNode6 = CreateBinaryTreeNode(6);
                BinaryTreeNode* pNode14 = CreateBinaryTreeNode(14);
                BinaryTreeNode* pNode4 = CreateBinaryTreeNode(4);
                BinaryTreeNode* pNode8 = CreateBinaryTreeNode(8);
                BinaryTreeNode* pNode12 = CreateBinaryTreeNode(12);
                BinaryTreeNode* pNode16 = CreateBinaryTreeNode(16);

                ConnectTreeNodes(pNode10, pNode6, pNode14);
                ConnectTreeNodes(pNode6, pNode4, pNode8);
                ConnectTreeNodes(pNode14, pNode12, pNode16);

                Test("Test1", pNode10);

                DestroyList(pNode4);
            }

            //               5
            //              /
            //             4
            //            /
            //           3
            //          /
            //         2
            //        /
            //       1
            void Test2()
            {
                BinaryTreeNode* pNode5 = CreateBinaryTreeNode(5);
                BinaryTreeNode* pNode4 = CreateBinaryTreeNode(4);
                BinaryTreeNode* pNode3 = CreateBinaryTreeNode(3);
                BinaryTreeNode* pNode2 = CreateBinaryTreeNode(2);
                BinaryTreeNode* pNode1 = CreateBinaryTreeNode(1);

                ConnectTreeNodes(pNode5, pNode4, nullptr);
                ConnectTreeNodes(pNode4, pNode3, nullptr);
                ConnectTreeNodes(pNode3, pNode2, nullptr);
                ConnectTreeNodes(pNode2, pNode1, nullptr);

                Test("Test2", pNode5);

                DestroyList(pNode1);
            }

            // 1
            //  \
            //   2
            //    \
            //     3
            //      \
            //       4
            //        \
            //         5
            void Test3()
            {
                BinaryTreeNode* pNode1 = CreateBinaryTreeNode(1);
                BinaryTreeNode* pNode2 = CreateBinaryTreeNode(2);
                BinaryTreeNode* pNode3 = CreateBinaryTreeNode(3);
                BinaryTreeNode* pNode4 = CreateBinaryTreeNode(4);
                BinaryTreeNode* pNode5 = CreateBinaryTreeNode(5);

                ConnectTreeNodes(pNode1, nullptr, pNode2);
                ConnectTreeNodes(pNode2, nullptr, pNode3);
                ConnectTreeNodes(pNode3, nullptr, pNode4);
                ConnectTreeNodes(pNode4, nullptr, pNode5);

                Test("Test3", pNode1);

                DestroyList(pNode1);
            }

            // 树中只有1个结点
            void Test4()
            {
                BinaryTreeNode* pNode1 = CreateBinaryTreeNode(1);
                Test("Test4", pNode1);

                DestroyList(pNode1);
            }

            // 树中没有结点
            void Test5()
            {
                Test("Test5", nullptr);
            }

            int main(int argc, char* argv[])
            {
                Test1();
                Test2();
                Test3();
                Test4();
                Test5();

                return 0;
            }

52. 面试题52:两个链表的第一个公共结点

        /*******************************************************************
        Copyright(c) 2016, Harry He
        All rights reserved.

        Distributed under the BSD license.
        (See accompanying file LICENSE.txt at
        https://github.com/zhedahht/CodingInterviewChinese2/blob/master/LICENSE.txt)
        *******************************************************************/

        //==================================================================
        // 《剑指Offer——名企面试官精讲典型编程题》代码
        // 作者:何海涛
        //==================================================================

        // 面试题52:两个链表的第一个公共结点
        // 题目:输入两个链表,找出它们的第一个公共结点。

        #include <cstdio>
        #include "..\Utilities\List.h"

        unsigned int GetListLength(ListNode* pHead);

        ListNode* FindFirstCommonNode(ListNode *pHead1, ListNode *pHead2)
        {
            // 得到两个链表的长度
            unsigned int nLength1 = GetListLength(pHead1);
            unsigned int nLength2 = GetListLength(pHead2);
            int nLengthDif = nLength1 - nLength2;

            ListNode* pListHeadLong = pHead1;
            ListNode* pListHeadShort = pHead2;
            if(nLength2 > nLength1)
            {
                pListHeadLong = pHead2;
                pListHeadShort = pHead1;
                nLengthDif = nLength2 - nLength1;
            }

            // 先在长链表上走几步,再同时在两个链表上遍历
            for(int i = 0; i < nLengthDif; ++i)
                pListHeadLong = pListHeadLong->m_pNext;

            while((pListHeadLong != nullptr) &&
                (pListHeadShort != nullptr) &&
                (pListHeadLong != pListHeadShort))
            {
                pListHeadLong = pListHeadLong->m_pNext;
                pListHeadShort = pListHeadShort->m_pNext;
            }

            // 得到第一个公共结点
            ListNode* pFisrtCommonNode = pListHeadLong;

            return pFisrtCommonNode;
        }

        unsigned int GetListLength(ListNode* pHead)
        {
            unsigned int nLength = 0;
            ListNode* pNode = pHead;
            while(pNode != nullptr)
            {
                ++nLength;
                pNode = pNode->m_pNext;
            }

            return nLength;
        }

        // ====================测试代码====================
        void DestroyNode(ListNode* pNode);

        void Test(char* testName, ListNode* pHead1, ListNode* pHead2, ListNode* pExpected)
        {
            if(testName != nullptr)
                printf("%s begins: ", testName);

            ListNode* pResult = FindFirstCommonNode(pHead1, pHead2);
            if(pResult == pExpected)
                printf("Passed.\n");
            else
                printf("Failed.\n");
        }

        // 第一个公共结点在链表中间
        // 1 - 2 - 3 \
        //            6 - 7
        //     4 - 5 /
        void Test1()
        {
            ListNode* pNode1 = CreateListNode(1);
            ListNode* pNode2 = CreateListNode(2);
            ListNode* pNode3 = CreateListNode(3);
            ListNode* pNode4 = CreateListNode(4);
            ListNode* pNode5 = CreateListNode(5);
            ListNode* pNode6 = CreateListNode(6);
            ListNode* pNode7 = CreateListNode(7);

            ConnectListNodes(pNode1, pNode2);
            ConnectListNodes(pNode2, pNode3);
            ConnectListNodes(pNode3, pNode6);
            ConnectListNodes(pNode4, pNode5);
            ConnectListNodes(pNode5, pNode6);
            ConnectListNodes(pNode6, pNode7);

            Test("Test1", pNode1, pNode4, pNode6);

            DestroyNode(pNode1);
            DestroyNode(pNode2);
            DestroyNode(pNode3);
            DestroyNode(pNode4);
            DestroyNode(pNode5);
            DestroyNode(pNode6);
            DestroyNode(pNode7);
        }

        // 没有公共结点
        // 1 - 2 - 3 - 4
        //
        // 5 - 6 - 7
        void Test2()
        {
            ListNode* pNode1 = CreateListNode(1);
            ListNode* pNode2 = CreateListNode(2);
            ListNode* pNode3 = CreateListNode(3);
            ListNode* pNode4 = CreateListNode(4);
            ListNode* pNode5 = CreateListNode(5);
            ListNode* pNode6 = CreateListNode(6);
            ListNode* pNode7 = CreateListNode(7);

            ConnectListNodes(pNode1, pNode2);
            ConnectListNodes(pNode2, pNode3);
            ConnectListNodes(pNode3, pNode4);
            ConnectListNodes(pNode5, pNode6);
            ConnectListNodes(pNode6, pNode7);

            Test("Test2", pNode1, pNode5, nullptr);

            DestroyList(pNode1);
            DestroyList(pNode5);
        }

        // 公共结点是最后一个结点
        // 1 - 2 - 3 - 4 \
        //                7
        //         5 - 6 /
        void Test3()
        {
            ListNode* pNode1 = CreateListNode(1);
            ListNode* pNode2 = CreateListNode(2);
            ListNode* pNode3 = CreateListNode(3);
            ListNode* pNode4 = CreateListNode(4);
            ListNode* pNode5 = CreateListNode(5);
            ListNode* pNode6 = CreateListNode(6);
            ListNode* pNode7 = CreateListNode(7);

            ConnectListNodes(pNode1, pNode2);
            ConnectListNodes(pNode2, pNode3);
            ConnectListNodes(pNode3, pNode4);
            ConnectListNodes(pNode4, pNode7);
            ConnectListNodes(pNode5, pNode6);
            ConnectListNodes(pNode6, pNode7);

            Test("Test3", pNode1, pNode5, pNode7);

            DestroyNode(pNode1);
            DestroyNode(pNode2);
            DestroyNode(pNode3);
            DestroyNode(pNode4);
            DestroyNode(pNode5);
            DestroyNode(pNode6);
            DestroyNode(pNode7);
        }

        // 公共结点是第一个结点
        // 1 - 2 - 3 - 4 - 5
        // 两个链表完全重合
        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);

            Test("Test4", pNode1, pNode1, pNode1);

            DestroyList(pNode1);
        }

        // 输入的两个链表有一个空链表
        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);

            Test("Test5", nullptr, pNode1, nullptr);

            DestroyList(pNode1);
        }

        // 输入的两个链表有一个空链表
        void Test6()
        {
            Test("Test6", nullptr, nullptr, nullptr);
        }

        void DestroyNode(ListNode* pNode)
        {
            delete pNode;
            pNode = nullptr;
        }

        int main(int argc, char* argv[])
        {
            Test1();
            Test2();
            Test3();
            Test4();
            Test5();
            Test6();

            return 0;
        }
12-16 08:50
查看更多