【链表】删除链表中的重复节点

题目描述

题目:输入一条链表,删除链表的中的重复节点,链表有序,且重复节点不保留,返回头结点指针,链表节点结构定义如下:

struct ListNode {
     int val;
     ListNode *next;
     ListNode(int x) 
         : val(x), next(NULL) 
    {}
};

例如:链表1 -> 2 -> 3 -> 3 -> 4 -> 4 -> 5,处理后的结果为:1 -> 2 -> 5

解题思路
  • 针对于此题,我们首先想到的是:将其分为重复和不重复两部分来进行讨论
  • 首先,从头节点开始遍历,若有两个节点的值是重复的,那么从当前节点开始遍历直到找到一个节点与前面值都不重复的
  • 从头结点开始遍历,如果两个节点的值不是重复的,那么我们需要将其与跳过重复部分后面的链表链接起来
  • 我们发现,整个链表的遍历过程中,我们一直在做重复上面两步的操作,所以我们很容易就可能想到递归的解决方式,思路理清楚后,我们就可以写代码了
代码实现
ListNode* deleteDuplication(ListNode* pHead)
{
    //若链表为空或者只有一个节点,则返回头节点
    if(pHead == NULL || pHead->next == NULLreturn pHead;
    //处理重复节点
    ListNode* cur = NULL;
    if(pHead->val == pHead->next->val)
    {
        cur = pHead->next;
        //找到与前面节点不重复的节点
        while(cur != NULL && cur->val == pHead->val)
        {
            cur = cur->next;
        }//此时,cur为空,或者它与前面节点不重复
        //删除前面重复节点,从cur节点开始,继续判断
        return deleteDuplication(cur);
    }
    else //处理非重复节点
    {
        //pHead->val != pHead->next->val
        cur = pHead->next;
        pHead->next = deleteDuplication(cur);
        return pHead;
    }
}
  • 完整代码实现+非递归版本:
ListNode* deleteDuplication(ListNode* pHead)
{
    if (pHead == NULL || pHead->next == NULL)
        return pHead;

    ListNode* cur = NULL;
    if (pHead->val == pHead->next->val)
    {
        cur = pHead->next->next;
        while (cur != NULL && cur->val == pHead->val)
        {
            cur = cur->next;
        }
        //返回第一个非重复节点,作为链表的头
        return deleteDuplication(cur);
    }
    else
    {
        cur = pHead->next;
        //将去除了重复节点后的前后链表链接起来
        pHead->next = deleteDuplication(cur);
        return pHead;
    }
}

//非递归版本
ListNode* deleteDuplicationNonR(ListNode* pHead)
{
    if (pHead == NULL || pHead->next == NULL)
        return pHead;

    //新建一个节点,防止头结点被删除
    ListNode* pNew = new ListNode(-1);
    pNew->next = pHead;
    ListNode* prev = pNew;
    ListNode* cur = pHead;
    ListNode* next = NULL;
    while (cur != NULL && cur->next != NULL)
    {
        next = cur->next;
        if (cur->val == cur->next->val)
        {
            while (next != NULL && next->val == cur->val)
            {
                next = next->next;
            }
            prev->next = next;
            cur = next;
        }
        else
        {
            prev = cur;
            cur = cur->next;
        }
    }
    return pNew->next;
}

void PrintList(ListNode* head)
{
    while (head != NULL)
    {
        printf("%d ->", head->val);
        head = head->next;
    }
    printf("over\n");
}

int main()
{
    ListNode* node1 = new ListNode(1);
    ListNode* node2 = new ListNode(2);
    ListNode* node3 = new ListNode(3);
    ListNode* node31 = new ListNode(3);
    ListNode* node4 = new ListNode(4);
    ListNode* node41 = new ListNode(4);
    ListNode* node5 = new ListNode(5);
    node1->next = node2;
    node2->next = node3;
    node3->next = node31;
    node31->next = node4;
    node4->next = node41;
    node41->next = node5;
    cout << "before:" << endl;
    PrintList(node1);
    cout << "after:" << endl;
    ListNode* head = deleteDuplication(node1);
    //ListNode* head = deleteDuplicationNonR(node1);
    PrintList(head);
    return 0;
}
  • 运行结果如下:
    删除重复节点

猜你喜欢

转载自blog.csdn.net/Aurora_pole/article/details/81380402
今日推荐