关于链表中去掉重复数值的问题

这篇博客讨论了如何从排序链表中删除重复的结点。首先介绍了问题背景,即在链表1->2->3->3->4->4->5中删除重复结点,使其变为1->2->5。接着,提出了两种解决方案:一种是针对已排序链表,通过新建头结点简化删除操作;另一种是在未排序情况下,使用map记录数值出现次数,若出现次数大于1则删除。文章提供了详细的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目:在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 

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

题目解析:首先是排序列表,把重复的所有值都删除,而不是保留一个重复值

第一种方法,建立一个新的头结点,就不需要考虑删除头节点和中间节点的区别,直接当做中间节点进行删除

详细代码如下:

 ListNode* deleteDuplication(ListNode* pHead)
    {
        if(pHead == NULL) return NULL;
        ListNode* myFirst = new ListNode(-1);//定义一个自己的头结点,就不用考虑头结点被删除的那种情况了
        myFirst->next = pHead;//这个节点指向头指针
        
        ListNode* p = pHead;//定义中间游动的指针
        ListNode* pre = myFirst;//定义前指针       
        while(p != NULL && p->next != NULL){
            if(p->val == p->next->val){
                int val = p->val;
                while(p != NULL && p->val == val){
                    p = p->next;//找到多个重复值的后第一个不重复值的位置
                }
                pre->next = p;  //前驱指针指向第一个不重复的,进行重复值的删除             
            }else{
                pre = p;
                p = p->next;
            }            
        }       
        return myFirst->next;//自定义指针的下一个才是头指针
 }

第二种方法
,不需要新建的结点,在删除节点时考虑中间节点和头结点两种情况

//单链表去除重复的数字**不添加头结点的情况,这个方法比较难理解**
 ListNode* deleteDuplicationOfHead(ListNode* pHead){
	  ListNode* pre = NULL;//定义前指针
        ListNode* p = pHead;//定义中间游动的指针
        ListNode* after = pHead->next;//指向相同值的最后一个
        bool flag;
        while(p!= NULL)
        {
            flag = false; 
            after = p->next;
            while(after!= NULL && p->val == after->val)
            {
                flag = true;
                after = after->next;
            }
            if(flag)
            {
                if(pre != NULL)//删除不是头结点
                {
                     pre->next = after;                 
                }
                else
                {
                    pHead = NULL;  //删除头结点
                }                              
            }
            else
            {  
               if(pre == NULL){pHead = p;}//我感觉删除头结点的方法很难想到
               pre = p;                                           
            }             
            p = after;//为什么加上这句话,在while循环中写p->next就会出现段错误,因为p就有可能为空了,空的next肯定就错了
        }      
        return pHead; 
 }


如果不是排序的数组,那应该怎么删除重复的数值呢,用一个map容器,把数值的值作为map的键值,数值出现的个数作为map的value值,如果出现value值大于1,则将其删除,具体代码如下:

ListNode* deleteDuplication(ListNode* pHead)
    {
        if(pHead==0) return 0;
 
        map<int,int> m;//把数组值作为key,数组中数值重复的个数做为value
        ListNode* p=pHead;
        while(p!=0)
        {
            m[p->val]++; //当key值相同时,value++
            p=p->next;
        }
        //判断head
        while(m[pHead->val]>1)
        {
            pHead = pHead->next;
            if(pHead==0) return 0;
        }
        ListNode* p1=pHead;
        ListNode* p2=pHead->next;
        while(p2!=0)
        {
            if(m[p2->val]>1)
            {
                p2=p2->next;
                p1->next=p2;
            }
            else
            {
                p2=p2->next;
                p1=p1->next;
            }
        }
        return pHead;
    }
};

如果不是把所有重复的节点都删了,而是保留把重复的节点删的只剩一个,这样就比较简单了,不用考虑头结点和中间节点的问题了。

具体代码如下所示:

ListNode* deleteDuplicationOfOnly(ListNode* ppHead){
	 ListNode *p ,*q;
	 p = ppHead;
	 q = ppHead->next;
	 while(q != NULL){	 
	 if(p->val == q->val && q != NULL){
	      p->next = q->next;
		  q = q->next;
	 }else{
		 p = p->next;
		 q = q->next;	  
	 } 
	}
	 return ppHead;
 }

这个链表指针的问题,思考了好几天,好吧,理解以上方法,也算有了收获。。。。。。。。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值