算法题15-16:删除有序链表中重复的元素

文章介绍了如何在有序链表中删除重复元素,提供了一类和二类两种解决方案。一类方案适用于所有重复元素的删除,而二类方案则会删除所有重复出现的元素,只保留原链表中只出现一次的元素。每种方法都通过调整指针来实现,避免了使用额外的数据结构。

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

算法题15:删除有序链表中重复的元素

1、第一类

删除给出链表中的重复元素(链表中元素从小到大有序),使链表中的所有元素都只出现一次。
在这里插入图片描述

代码

ListNode* deleteDuplicates(ListNode* head) {
        // write code here
        if(head==NULL || head->next==NULL) return head;

        ListNode *pre = head;
        ListNode *cur = head->next;
        while(cur!=NULL){
            // 如果结点值与前一个结点值相同,删除当前结点
            if(cur->val == pre->val){
                pre->next = cur->next;
                cur = pre->next;
            }
            else{
                cur = cur->next;
                pre = pre->next;
            }
        }
        return head;
    }

2、第二类

给出一个升序排序的链表,删除链表中的所有重复出现的元素,只保留原链表中只出现一次的元素。
在这里插入图片描述

思路

  • 在第一类问题的基础上,需要删除所有重复元素的第一个结点,因此将pre和cur指针的位置向前移动一位,初始时将pre设置为新的头结点,防止第一个结点就出现重复从而将原head结点删除的情况出现;
  • 比较cur和cur->next结点的值,如果相等则删去重复的结点,即cur->next结点,并记录repeat为true,进行下一轮循环;
  • 当cur和cur->next结点的值不等时,需要判断是否存在repeat,如果存在,说明当前cur结点为重复结点,需要删去;如果不存在,则pre和cur依次移位,进入下一轮循环;
  • 最后需要单独处理最后一个结点。

代码

ListNode* deleteDuplicates(ListNode* head) {
        // write code here

        if(head==NULL || head->next==NULL) return head;

        ListNode *pre = new ListNode(0); //添加一个表头结点,防止将原链表的头结点删除而无法输出链表
        pre->next = head;
        head = pre; //新的头结点
        //ListNode *pre = NULL; //前一个结点,为了删除第一个重复的结点
        ListNode *cur = head; //当前结点
        bool repeat = false; //当前结点是否发生重复
        while(cur->next != NULL){
            if(cur->next->val == cur->val){
                cur->next = cur->next->next; //删除后面重复的结点
                repeat = true;
            }
            else if(repeat){
                pre->next = cur->next; //删除第一个重复结点
                cur = pre->next;
                repeat = false;
            }
            else{
                pre = cur;
                cur = cur->next;
            }
        }
        // 处理最后一个结点
        if(repeat){
            if(pre==NULL) return NULL;
            else pre->next = cur->next;
        }
        return head->next;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值