82. 删除排序链表中的重复元素 II

1,111 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第16天,点击查看活动详情

题目描述

给定一个已排序的链表的头 head , 删除原始链表中所有重复数字的节点,只留下不同的数字 。返回 已排序的链表 。

截屏2022-04-21 下午1.40.46.png

思路分析

由于数组已经排序,所以只需要遍历一遍即可。我们先考虑一种去重的算法,

输入: head = [1,2,3,3,4,4,5]
输出: [1,2,3,4,5]

这种算法很简单,只需要遍历每个节点的时候比较其pre节点,如果pre.val = node.val 则将node删除,pre节点保持不变。

而如果pre.val != node.val 则需要将pre节点后移一位,也就是node的位置,继续遍历

而如果要删除所有重复节点而不是简单的去重,那就难了。当pre.val = node.val 时, 则需要将pre节点前移,那样就需要有一个prepre节点,(当然由于链表本身是已经排序的,所以这种情况只会发生一次)

这样的话最初也要设置一下两个头节点

代码实现

ListNode* deleteDuplicates(ListNode* head) {
        ListNode* reaHead = new ListNode(-101);
        ListNode* preHead = new ListNode(-101);

        reaHead -> next = preHead;
        preHead -> next = head;
        bool flag = false;
        ListNode* prepre = reaHead;
        ListNode* pre = preHead;
        ListNode* node = head;
        while(node != nullptr){
            if(node->val == pre->val){
                pre ->next = node -> next;
                node = node -> next;
                flag = true;
            }else{
                if(flag) {
                    prepre -> next = node;
                    pre = node;
                    node = node -> next;
                    flag = false;
                }else{
                    node = node -> next;
                    pre = pre->next;
                    prepre = prepre -> next;
                }
            }
            
        }
        if(flag) {
                // cout << prepre -> val;
                // cout << "1" << endl;
                    prepre -> next = node;
                    pre = node;
                    // node = node -> next;
                    flag = false;
            }
        return reaHead -> next -> next;
    }

总结

这道题其实难度并不是很大,不过实践中还是遇到了一些问题,比如【1,1】这种情况其实应该都删除,但是最初并没有在while外面加一层判断逻辑,导致会遗漏一个1.