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

问题描述

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

提示:

  • 链表中节点数目在范围 [0, 300]
  • -100 <= Node.val <= 100
  • 题目数据保证链表已经按升序 排列

示例

示例 1:

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

示例 2:

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

解题思路

本题要注意的是要把所有重复数字的节点都删除。例如,[1,1,1] 删除后是 [],而不是 [1]。我们可以使用双指针来实现删除操作,具体做法为:

此时pre->next->val != cur->val,我们将 curpre 都指向下一个节点即可。 注意,我们在表头新增了一个节点,这样就能处理链表起始节点的值是重复的情况。

此时还是可以继续将 precur 指针向后移。

此时, pre->next->val == cur->val,应该要将这两个节点删除。同时,我们还是要先找到 cur 所指向的下一个节点的位置。

我们将值为 3 的节点删除,并将 pre->next 指向后面第一个值不为 3 的节点。同时令 cur 指向 pre->next 的下一个节点。此时我们发现 pre->next->val == cur->val,因此我们继续上面的步骤。

我们发现,cur 此时已经变成了 nullpr,这说明我们已经遍历完链表了,并得到了最终结果。最终代码如下:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* deleteDuplicates(ListNode* head) {
        if(head == nullptr || head->next == nullptr){
            return head;
        }
        ListNode* cur = new ListNode(200);
        cur->next = head;
        head = cur;
        cur = head->next->next;
        ListNode* pre = head;
        ListNode* tmp = nullptr;
        while(cur != nullptr){
            if(pre->next->val == cur->val){ // 判断当前节点是否需要删除
                tmp = cur->next;
                while(tmp != nullptr){ // 寻找后面第一个值不为 pre->next->val 的节点
                    if(tmp->val == cur->val){ // 值相同时,将这些多余的节点删除
                        tmp = tmp->next;
                        delete cur->next;
                        cur->next = tmp;
                    }
                    else{ // 已经找到了
                        break;
                    }
                }
                delete cur;
                cur = nullptr;
                delete pre->next; //删除pre->next和cur这两个重复节点
                pre->next = nullptr;
                if(tmp == nullptr){ // 说明已经找到了末尾,可以直接返回最终结果了
                    return head->next;
                }
                else if(tmp->next == nullptr){ // 说明后面只有一个节点,也可以直接返回了
                    pre->next = tmp;
                    return head->next;
                }
                else{ // 后续还有很多节点,继续查找
                    pre->next = tmp;
                    cur = tmp->next;
                }
            }
            else{ // 无重复值
                pre = pre->next;
                cur = cur->next;
            }
        }
        return head->next;
    }
};

可以看到,上述代码的关键就是保证 precur 指针之间间隔一个元素。

posted @ 2022-12-01 12:06  greatestchen  阅读(13)  评论(0编辑  收藏  举报