链表去重

本文介绍了两种不同的链表去重算法,一种保留原始链表中没有重复出现的数字,另一种保留所有元素但只出现一次。这两种方法都针对已排序的链表,通过比较前后节点值来判断是否重复,并构建新的无重复元素链表。关键点包括处理空节点、正确追加节点以及设置队尾节点的next为空。
摘要由CSDN通过智能技术生成

链表去重 82

存在一个按升序排列的链表,给你这个链表的头节点 head ,请你删除链表中所有存在数字重复情况的节点,只保留原始链表中 没有重复出现 的数字。返回同样按升序排列的结果链表

在这里插入图片描述例子

思路:因为是已经排好序的链表所以只需要比较前后就知道该节点的值是否是重复


/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */


struct ListNode* deleteDuplicates(struct ListNode* head){
        if(head==0||head->next==0) return head;
        int val=head->val;
        struct ListNode *p=head;   
        struct ListNode *pn=p->next->next;  //下个
        struct ListNode *pre=head;  //前面的一个
        struct ListNode *ln=0;   //返回链表的尾
        p=p->next;    
        if(p->val!=pre->val) ln=head;  //尝试确定表头
        while(pn){
            while(pn&&(p->val==pre->val||pn->val==p->val)){ //比较跟之前跟后面的是否一样
                pre=pre->next;
                p=p->next;
                pn=pn->next;
            }
            if(pn){ //如果是因为下个为空结束,那么结束循环,否则将p加入新链表
                pn=pn->next;
            }else{
                break;
            }
            if(ln==0){ //若队首确定了则加入,否则新加入的为表头
                ln=p;
                head=ln;
            }else{
                ln->next=p;
                ln=ln->next;
            }
            
            pre=pre->next;
            p=p->next;
        }
        
        if(pre->val!=p->val){ //看看最后一个符不符合要求
           if(ln==0){
                ln=p;
                head=ln;
            }else{
                ln->next=p;
                ln=ln->next;
            }
        }
        if(ln==0) return ln;  //如果表头仍为空 返回
        ln->next=0;
        return head;
}

删除链表重复元素,力扣83
存在一个按升序排列的链表,给你这个链表的头节点 head ,请你删除所有重复的元素,使每个元素 只出现一次 。返回同样按升序排列的结果链表
在这里插入图片描述
这题跟上面的区别在于,需要保留重复元素,采用类似于队列的思想,将新的元素跟队尾的元素相比较如果在队尾中那么去寻找下一个,如果跟队尾元素不相等,则将节点加入。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */


struct ListNode* deleteDuplicates(struct ListNode* head){
      if(head==0) return head; 
      struct ListNode* pre=head; //pre为队尾节点
      struct ListNode* p=pre->next;
      while(p){
          while(p&&p->val!=pre->val){ //如果p不为空节点,且p不和队尾相等则就把p节点加入
              pre->next=p;
              p=p->next;
              pre=pre->next;
            }
            if(p==0) break; 如果p等于0 ,则结束
            p=p->next;
      }
      pre->next=0;
      return head;
        
}

总结:在处理链表类问题的时候存在的一些问题:1)空节点问题,因为表头可能为空要注意
2)在新生成的链表的时候,队尾节点的next一定要设为空
3)在追加节点的时候p=p->next 也不能忘记
4) malloc 的资源需要释放

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值