剑指Offer(第2版)——面试题18:删除链表中重复的节点

题目:

在一个排序的链表中,存在重复的节点,请删除该链表中重复的节点,重复的节点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5。

解题思路:

三指针法:

  • 删除重复节点,只需要记录当前节点之前的最晚访问过的不重复节点pPre、当前节点pCur、指向当前节点之后节点pNext的三个指针即可;
  • 如果当前节点和它后面的几个节点数值相同,那么这些节点都要被剔除,然后更新pPre和pCur;如果不相同,则直接更新pPre和pCur;
  • 需要考虑的是,如果第一个节点是重复节点我们该怎么办?这里我们分别处理一下就好,如果第一个节点是重复节点,那么就把头指针pHead也更新一下。

2.代码:

class Solution{
public:
    ListNode* deleteDuplication(ListNode* pHead){
        //判断 pHead是否指向为空,pHead指向链表第一个元素
        if(pHead == NULL) return NULL;

        ListNode* pPre = NULL; //指向当前节点之前最晚访问过的不重复节点
        ListNode* pCur = pHead; //指向当前处理的节点
        ListNode* pNext = NULL; //指向当前节点之后的节点

        //循环判断条件是 pCur指针指向是否为空
        while(pCur != NULL){
            //如果下个节点不为空 且当前节点与下个节点值相同
            if(pCur->next != NULL && pCur->next->val == pCur->val){
                pNext = pCur->next;
                //pNext 继续向后移动,直到当前节点与下一个节点值不相同为止
                while(pNext->next != NULL && pNext->next->val == pCur->val){
                    pNext = pNext->next;
                }

                //删除阶段
                //如果pCur指向链表中的第一个元素,pCur -> ... -> pNext ->...
                //要删除pCur到pNext(包含两者), 将指向链表第一个元素的指针pHead指向pNext->next
                if(pCur == pHead) pHead = pNext->next;

                //如果pCur不指向链表中第一个元素,pPre -> pCur ->...->pNext ->... 
                //要删除pCur到pNext,即pPre->next = pNext->next   
                else pPre->next = pNext->next;

                //删除后pCur重新调整
                pCur = pNext->next;
            }

            //如果当前节点值与下一个节点值不相同,整体移位
            else{
                pPre = pCur;
                pCur = pCur->next;
            }
        }
        return pHead;
    }
};

简洁版:

class Solution{
public:
    ListNode* deleteDuplication(ListNode* pHead){
        //判断 pHead是否为空
        if(!pHead) return NULL;
        //设定第一个节点值为参照值(不变)
        int val = pHead->val;     
        
        //判断下一个节点是否为空
        if(pHead->next){
            //如果下一个节点与参照值相同
            if(pHead->next->val == val){
                //向后移动pHead,直到节点值与val不相同为止
                //这里的val指的是第一个pHead->val(前提:节点重复的话会在连在一起)
                //如果重复节点不在一起,如何处理??
                while(pHead && pHead->val == val) pHead = pHead->next;
                return deleteDuplication(pHead);
            }

            //下一个节点与当前节点值不相同时
            else{
                pHead->next = deleteDuplication(pHead->next);
                return pHead;
            }
        }
        else return pHead;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值