zoukankan      html  css  js  c++  java
  • 剑指offer

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

    ListNode* FindFirstNode(ListNode* HeadNode)
    {
        if(!HeadNode)
            return nullptr;
        ListNode* FastNode = HeadNode;
        ListNode* SlowNode = HeadNode;
        while(FastNode&(FastNode->NextPoint))
        {
            SlowNode = SlowNode->NextPoint;
            FastNode = SlowNode->NextPoint;
            if(FastNode == SlowNode)
            {
                SlowNode = HeadNode;
                while(FastNode != SlowNode)
                {
                    FastNode = FastNode->NextPoint;
                    SlowNode = SlowNode->NextPoint;
                }
                return SlowNode;
            }
        }
        return nullptr;
    }


    //找到链表中环形链表的入口点
    ListNode* FindTheFirstNode(ListNode* Node)
    {
        if(Node ==nullptr)
            return nullptr;
        ListNode* Fastp = Node;
        ListNode  Slowp = Node;
        while((Fastp!= Slowp)&(Fastp!=nullptr))
        {
            Fastp = Fastp->NextPoint->NextPoint;
            Slowp = Slowp->NextPoint;
        }
        Slowp =Node;
        while(SLowp != Fastp)
        {
            Slowp = Slowp->NextPoint;
            Fastp = Fastp->NextPoint;
        }
        return slowp;
    }
    

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

    #include <cstdio>
    #include "..UtilitiesList.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:=====
    ");
        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.
    ");
        ListNode* pNode = FindKthToTail(pNode1, 2);
        PrintListNode(pNode);
    
        DestroyList(pNode1);
    }
    
    // 测试要找的结点是链表的尾结点
    void Test2()
    {
        printf("=====Test2 starts:=====
    ");
        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.
    ");
        ListNode* pNode = FindKthToTail(pNode1, 1);
        PrintListNode(pNode);
    
        DestroyList(pNode1);
    }
    
    // 测试要找的结点是链表的头结点
    void Test3()
    {
        printf("=====Test3 starts:=====
    ");
        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.
    ");
        ListNode* pNode = FindKthToTail(pNode1, 5);
        PrintListNode(pNode);
    
        DestroyList(pNode1);
    }
    
    // 测试空链表
    void Test4()
    {
        printf("=====Test4 starts:=====
    ");
        printf("expected result: nullptr.
    ");
        ListNode* pNode = FindKthToTail(nullptr, 100);
        PrintListNode(pNode);
    }
    
    // 测试输入的第二个参数大于链表的结点总数
    void Test5()
    {
        printf("=====Test5 starts:=====
    ");
        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.
    ");
        ListNode* pNode = FindKthToTail(pNode1, 6);
        PrintListNode(pNode);
    
        DestroyList(pNode1);
    }
    
    // 测试输入的第二个参数为0
    void Test6()
    {
        printf("=====Test6 starts:=====
    ");
        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.
    ");
        ListNode* pNode = FindKthToTail(pNode1, 0);
        PrintListNode(pNode);
    
        DestroyList(pNode1);
    }
    
    int main(int argc, char* argv[])
    {
        Test1();
        Test2();
        Test3();
        Test4();
        Test5();
        Test6();
    
        return 0;
    }

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

    #include <cstdio>
    #include "..UtilitiesList.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.
    ");
        else
            printf("Failed.
    ");
    }
    
    // 第一个公共结点在链表中间
    // 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;
    }
    

     // 面试题51:数组中的逆序对
    // 题目:在数组中的两个数字如果前面一个数字大于后面的数字,则这两个数字组
    // 成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。

     

    #include <cstdio>
    
    int InversePairsCore(int* data, int* copy, int start, int end);
    
    int InversePairs(int* data, int length)
    {
        if(data == nullptr || length < 0)
            return 0;
    
        int* copy = new int[length];
        for(int i = 0; i < length; ++i)
            copy[i] = data[i];
    
        int count = InversePairsCore(data, copy, 0, length - 1);
        delete[] copy;
    
        return count;
    }
    
    int InversePairsCore(int* data, int* copy, int start, int end)
    {
        if(start == end)
        {
            copy[start] = data[start];
            return 0;
        }
    
        int length = (end - start) / 2;
    
        int left = InversePairsCore(copy, data, start, start + length);
        int right = InversePairsCore(copy, data, start + length + 1, end);
    
        // i初始化为前半段最后一个数字的下标
        int i = start + length;
        // j初始化为后半段最后一个数字的下标
        int j = end;
        int indexCopy = end;
        int count = 0;
        while(i >= start && j >= start + length + 1)
        {
            if(data[i] > data[j])
            {
                copy[indexCopy--] = data[i--];
                count += j - start - length;
            }
            else
            {
                copy[indexCopy--] = data[j--];
            }
        }
    
        for(; i >= start; --i)
            copy[indexCopy--] = data[i];
    
        for(; j >= start + length + 1; --j)
            copy[indexCopy--] = data[j];
    
        return left + right + count;
    }
    
    // ====================测试代码====================
    void Test(char* testName, int* data, int length, int expected)
    {
        if(testName != nullptr)
            printf("%s begins: ", testName);
    
        if(InversePairs(data, length) == expected)
            printf("Passed.
    ");
        else
            printf("Failed.
    ");
    }
    
    void Test1()
    {
        int data[] = { 1, 2, 3, 4, 7, 6, 5 };
        int expected = 3;
    
        Test("Test1", data, sizeof(data) / sizeof(int), expected);
    }
    
    // 递减排序数组
    void Test2()
    {
        int data[] = { 6, 5, 4, 3, 2, 1 };
        int expected = 15;
    
        Test("Test2", data, sizeof(data) / sizeof(int), expected);
    }
    
    // 递增排序数组
    void Test3()
    {
        int data[] = { 1, 2, 3, 4, 5, 6 };
        int expected = 0;
    
        Test("Test3", data, sizeof(data) / sizeof(int), expected);
    }
    
    // 数组中只有一个数字
    void Test4()
    {
        int data[] = { 1 };
        int expected = 0;
    
        Test("Test4", data, sizeof(data) / sizeof(int), expected);
    }
    
    
    // 数组中只有两个数字,递增排序
    void Test5()
    {
        int data[] = { 1, 2 };
        int expected = 0;
    
        Test("Test5", data, sizeof(data) / sizeof(int), expected);
    }
    
    // 数组中只有两个数字,递减排序
    void Test6()
    {
        int data[] = { 2, 1 };
        int expected = 1;
    
        Test("Test6", data, sizeof(data) / sizeof(int), expected);
    }
    
    // 数组中有相等的数字
    void Test7()
    {
        int data[] = { 1, 2, 1, 2, 1 };
        int expected = 3;
    
        Test("Test7", data, sizeof(data) / sizeof(int), expected);
    }
    
    void Test8()
    {
        int expected = 0;
    
        Test("Test8", nullptr, 0, expected);
    }
    
    int main(int argc, char* argv[])
    {
        Test1();
        Test2();
        Test3();
        Test4();
        Test5();
        Test6();
        Test7();
        Test8();
    
        return 0;
    }
    

      

  • 相关阅读:
    Encryption (hard) CodeForces
    cf 1163D Mysterious Code (字符串, dp)
    AC日记——大整数的因子 openjudge 1.6 13
    AC日记——计算2的N次方 openjudge 1.6 12
    Ac日记——大整数减法 openjudge 1.6 11
    AC日记——大整数加法 openjudge 1.6 10
    AC日记——组合数问题 落谷 P2822 noip2016day2T1
    AC日记——向量点积计算 openjudge 1.6 09
    AC日记——石头剪刀布 openjudge 1.6 08
    AC日记——有趣的跳跃 openjudge 1.6 07
  • 原文地址:https://www.cnblogs.com/hai5111/p/11423633.html
Copyright © 2011-2022 走看看