zoukankan      html  css  js  c++  java
  • 《剑指offer》第十八题II:删除链表中重复的结点

    // 面试题18(二):删除链表中重复的结点
    // 题目:在一个排序的链表中,如何删除重复的结点?例如,在图3.4(a)中重复
    // 结点被删除之后,链表如图3.4(b)所示。
    
    #include <cstdio>
    #include "list.h"
    
    void DeleteDuplication(ListNode** pHead) //可能需要修改头指针
    {
        if (pHead == nullptr || *pHead == nullptr)
            return;
    
        ListNode* pNodePre = nullptr; //待删除节点的前一个节点
        ListNode* pNode = *pHead;
    
        while (pNode != nullptr)
        {
            ListNode* pNext = pNode->m_pNext; //当前节点的下一节点
            bool needDelete = false; //标志位
            if (pNext != nullptr && pNode->m_nValue == pNext->m_nValue)
                needDelete = true;
    
            //无重复
            if (!needDelete)
            {
                pNodePre = pNode;
                pNode = pNode->m_pNext;
            }
            //有重复
            else
            {
                int value = pNode->m_nValue; //重复的data
                ListNode* pToBeDel = pNode;
                //只要重复就一直删除
                while (pToBeDel != nullptr && pToBeDel->m_nValue == value)
                {
                    pNext = pToBeDel->m_pNext; //记录链表删除后部的指针
    
                    delete pToBeDel;
                    pToBeDel = nullptr;
                    pToBeDel = pNext;
                }
                if (pNodePre == nullptr) //要是前一节点为空, 设置其下一节点为头节点
                    *pHead = pNext;
                else //否则,连接前后链表
                    pNodePre->m_pNext = pNext;  
                pNode = pNext;
            }
        }
    }
    // ====================测试代码====================
    void Test(const 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.
    ");
        else
            printf("FAILED.
    ");
    }
    
    // 某些结点是重复的
    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;
    }
    测试代码
    /*
    struct ListNode {
        int val;
        struct ListNode *next;
        ListNode(int x) :
            val(x), next(NULL) {
        }
    };
    */
    class Solution {
    public:
        ListNode* deleteDuplication(ListNode* pHead)
        {
            if (pHead == nullptr)
                return nullptr;
            
            ListNode* pPreNode = nullptr;
            ListNode* pNode = pHead;
            
            while (pNode != nullptr)
            {
                ListNode* pNext = pNode->next;
                bool needDelete = false;
                if (pNext != nullptr && pNode->val == pNext->val)
                    needDelete = true;
                
                if (!needDelete)
                {
                    pPreNode = pNode;
                    pNode = pNode->next;
                }
                else
                {
                    int value = pNode->val;
                    ListNode* pToBeDel = pNode;
                    while (pToBeDel != nullptr && pToBeDel->val == value)
                    {
                        pNext = pToBeDel->next;
                        delete pToBeDel;
                        pToBeDel = nullptr;
                        pToBeDel = pNext;
                    }
                    if (pPreNode == nullptr)
                        pHead = pNext;
                    else
                        pPreNode->next = pNext;
                    pNode = pNext;
                }
            }
            return pHead;
        }
    };
    牛客网提交代码
  • 相关阅读:
    Kafka相关知识点
    好的前端界面
    linux下配置go环境
    插入排序(数据是局部有序的)
    选择排序
    spring jpa 条件查询统计
    java代码优化
    JAVA创建临时文件IO
    spring防止表单重复提交
    Java文件下载时所输出文件名乱码问题
  • 原文地址:https://www.cnblogs.com/ZSY-blog/p/12562933.html
Copyright © 2011-2022 走看看