C/C++ BM16 删除有序链表中重复的元素-II

前言

这道题和BM15稍有些差别,一开始做的时候还是按照BM15的方法来做,结果想了半天发现自己路走窄了。

这道题也是删除节点的方式,不过可能出现删除或者说跳过节点数不固定的情况,这种情况在处理的时候,我一开始用一个变量来保存要处理的节点个数,最后发现,这样做很麻烦,要考虑多种情况。


题目

描述
给出一个升序排序的链表,删除链表中的所有重复出现的元素,只保留原链表中只出现一次的元素。
例如:
给出的链表为 1 → 2 → 3 → 3 → 4 → 4 → 5 1→2→3→3→4→4→5 1233445, 返回 1 → 2 → 5 1→2→5 125
给出的链表为 1 → 1 → 1 → 2 → 3 1→1→1→2→3 11123 返回 2 → 3 2→3 23.

数据范围:链表长度 0 ≤ n ≤ 10000 0≤n≤10000 0n10000,链表中的值满足 ∣ v a l ∣ ≤ 1000 ∣val∣≤1000 val∣≤1000
要求:空间复杂度 O ( n ) O(n) O(n),时间复杂度 O ( n ) O(n) O(n)
进阶:空间复杂度 O ( 1 ) O(1) O(1),时间复杂度 O ( n ) O(n) O(n)

示例1
输入:{1,2,2}
返回值:{1}

示例2
输入:{}
返回值:{}

解决方案一

1.1 思路阐述

对于BM15来说,始终要保留一个节点,但是BM16里面,凡是相同的节点,都要删除。这就会出现第一个节点就要删除的情况。
所以我们在处理节点的时候需要知道删除节点的前驱节点,因此在整个链表中需要一个表头,作为初始链表的前驱结点。

因为删除的节点可能不止两个,会有更多的重复,所以需要跳过相同的节点,找到下一个不同的节点,这就涉及到新的循环判断。

最后返回的链表应该是自己添加的表头的下一个节点开始的链表。

具体做法:
step 1:给链表前加上表头,方便可能的话删除第一个节点。
step 2:遍历链表,每次比较相邻两个节点,如果遇到了两个相邻节点相同,则新开内循环将这一段所有的相同都遍历过去。
step 3:在step 2中这一连串相同的节点前的节点直接连上后续第一个不相同值的节点。
step 4:返回时去掉添加的表头。

1.2 源码

class Solution {
public:
    ListNode* deleteDuplicates(ListNode* head) {
        //空链表
        if(head == NULL) 
            return NULL;
        ListNode* res = new ListNode(-1);
        //在链表前加一个表头
        res->next = head; 
        ListNode* cur = res;
        
        while(cur->next != NULL && cur->next->next != NULL){ 
            //遇到相邻两个节点值相同
            if(cur->next->val == cur->next->next->val){ 
                int temp = cur->next->val;
                //将所有相同的都跳过
                while (cur->next != NULL && cur->next->val == temp) 
                    cur->next = cur->next->next;
            }
            else 
                cur = cur->next;
        }
        //返回时去掉表头
        return res->next; 
    }
};

总结

BM15与BM16属于同类型问题,BM16是进阶。

这类问题主要在于删除节点的操作,链表中删除节点涉及到当前节点的删除和下一个节点的删除大致这两种情况。

当前节点的删除的话,需要知道当前节点的前驱结点,所以在一开始就要有一个前驱结点对应的指针。
下一个节点删除的话,因为是下一个节点,所以当前节点就是下一个节点的前驱结点,因此这种删除比较方便。

  • 47
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

澄澈i

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值