剑指offer[18-2] 删除了链表中重复的节点(不保留)

我今天真的是心态崩了,我的天,自己写了一遍没有通过,又按照书上的又敲了一遍还是提示通过率为0,我太难了

今天就来细细的分析这个!

上题目:

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

题目解析:

主要考察删除链表中的节点,特殊的地方就在于删除重复出现过的节点(一个也不保留),同时链表又是排序后的,因此重复的节点肯定是挨着的(记住这句话,不然很尴尬)。

思路:使用两个指针,1)一个用来遍历整个链表 (额,我好像有点废话了,,,

                                    2)用来将不重复的节点串起来

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
        val(x), next(NULL) {
    }
};
*/
class Solution {
public:
    ListNode* deleteDuplication(ListNode* pHead)
    {
        if(pHead==nullptr || pHead->next==nullptr) return pHead;
        ListNode* pPre = nullptr; // 用于链接不重复的节点
		ListNode* result = nullptr;// 链接不重复的节点的头指针  
        ListNode* pCurrent = pHead; // 用于遍历整个链表
        bool isFirst = true;
        while(pCurrent!=nullptr) { 
            bool isDelete = false;  // 判断节点是否需要删除
            ListNode* pNext = pCurrent->next;  // 当前节点的下一个节点
            if(pCurrent->next!=nullptr && pCurrent->val == pNext->val) // 删除条件-》重复
                isDelete = true;
            if(!isDelete) {
                if(isFirst) {  // 因为开始的时候初始化为nullptr所以需要设置一下
                    pPre = pCurrent;
                    result = pPre; // 用于链接不重复的节点的头指针 这里就是我犯傻的地方,我居然没留一个头指针,直接将pPre返回了。。。
			        isFirst = false;   //表明头指针不为空
                } else {
                    pPre->next = pCurrent; // 不是第一个节点
                    pPre = pPre->next;
                }
            } else {
                int val = pCurrent->val;  //回去待删除的节点的值,因为重复可能为多次
                ListNode *pDelete = pCurrent;  //用于删除重复值
                while(pDelete!=nullptr && pDelete->val == val) {
                    pNext = pDelete ->next;
                    delete pDelete;
                    pDelete = nullptr;
                    pDelete = pNext;
                }
                
            }
              pCurrent = pNext; // 更新原始链表中的pCurrent
        }
        if(pPre!=nullptr) pPre->next=nullptr;  //对尾部进行处理
        return result;  //返回头指针
       
    }
};

 下面还有大佬写的递归格式的,怎一个牛逼了得!:

链接:https://www.nowcoder.com/questionTerminal/fc533c45b73a41b0b44ccba763f866ef?answerType=1&f=discussion
来源:牛客网

//递归求解 C++ 有问请指出谢谢,
//理解递归了写起来代码蛮简单,研读别人代码这个过程异常艰难耗时,所以我把思路都写出来了方便理解;
//每次递归:删除当前指针向后的连续节点。保证下一次递归的头结点与之后的不重复;找到下一个不重复的节点与其相连
class Solution {
public:
    ListNode* deleteDuplication(ListNode* pHead)
    {
        if (!pHead || !pHead->next) return pHead;//0/1个结点直接返回头,也是递归出口,NULL的话结束
        ListNode* cur;
        if ( pHead->next->val==pHead->val){//当前结点等于下一个
            cur=pHead->next;//cur指向下一个
            while (cur->next && cur->next->val==pHead->val)//有下一个且还想等
                cur=cur->next;//走到相等的最后一个,此节点和前面的还是相等的
            return deleteDuplication(cur->next);//递归往后第一个不相等的,NULL的话结束             
        }
        else {//此节点和下个不相等
            cur=pHead->next;//下个结点递归过去
            pHead->next=deleteDuplication(cur);//重构链表
            return pHead;//每次返回的都是头
        }    
    }
};

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值