​BM16 删除有序链表中重复的元素-II​

知识点​链表​

描述

给出一个升序排序的链表,删除链表中的所有重复出现的元素,只保留原链表中只出现一次的元素。

例如:

给出的链表为[链表]BM16 删除有序链表中重复的元素-II-中等_链表, 返回[链表]BM16 删除有序链表中重复的元素-II-中等_删除重复元素_02.

给出的链表为[链表]BM16 删除有序链表中重复的元素-II-中等_快慢节指针_03, 返回[链表]BM16 删除有序链表中重复的元素-II-中等_删除重复元素_04.

数据范围:链表长度 [链表]BM16 删除有序链表中重复的元素-II-中等_链表_05,链表中的值满足 [链表]BM16 删除有序链表中重复的元素-II-中等_快慢节指针_06要求:空间复杂度 [链表]BM16 删除有序链表中重复的元素-II-中等_链表_07,时间复杂度 [链表]BM16 删除有序链表中重复的元素-II-中等_链表_07进阶:空间复杂度 [链表]BM16 删除有序链表中重复的元素-II-中等_删除重复元素_09,时间复杂度 [链表]BM16 删除有序链表中重复的元素-II-中等_链表_07

示例1

输入:

{1,2,2}

返回值:

{1}


示例2

输入:

{}

返回值:

{}

题解

使用计数器的解法

思路:

遍历整个链表,使用一个计数器对重复的节点进行计数,如果节点个数是1则加入链表中,实现如下:

#include <bits/stdc++.h>

struct ListNode
{
int val;
struct ListNode *next;
ListNode(int x) : val(x), next(nullptr)
{
}
ListNode() = default;
};

ListNode *deleteDuplicates(ListNode *head)
{
if (head == nullptr || head->next == nullptr)
{
return head;
}

ListNode *first_node = nullptr;
ListNode *tail_node = nullptr;
ListNode *cur_node = head;
int count = 1;
while (cur_node != nullptr)
{
if (cur_node->next == nullptr)
{
if (count == 1)
{
if (first_node == nullptr)
{
first_node = cur_node;
first_node->next = nullptr;
}
else
{
tail_node->next = cur_node;
}
}
else
{
if (tail_node != nullptr)
{
tail_node->next = nullptr;
}
}
break;
}
else
{
auto next_node = cur_node->next;
if (cur_node->val == next_node->val)
{
count++;
cur_node = next_node;
}
else
{
if (count == 1)
{
if (first_node == nullptr)
{
first_node = cur_node;
tail_node = cur_node;
tail_node->next = nullptr;
}
else
{
tail_node->next = cur_node;
tail_node = tail_node->next;
}
}

count = 1;
cur_node = next_node;
}
}
}
return first_node;
}

使用快慢指针的解法

  • 思路:双指针:fast探测并跳过重复的节点,slow指向已检查过的最后一个,使用slow->next = fast删除重复的节点
  • 难点:头节点也可能要删除。这里往头部之前加一个虚拟头部vhead,让slow先指向vhead
ListNode *deleteDuplicates(ListNode *head)
{
ListNode *vHead = new ListNode(0);
vHead->next = head;
ListNode *fast = head;
ListNode *slow = vHead;
while (fast && fast->next)
{
if (fast->next->val != fast->val)
{ //检测fast指向的节点是否重复
slow = fast; //不重复,slow往前一步
fast = fast->next;
}
else
{
int repeatVal = fast->val; //记录重复的值,让fast跳过全部值相同的节点
while (fast && fast->val == repeatVal)
{
fast = fast->next;
}
slow->next = fast; //注意此时fast指向的节点仍可能重复,所以slow不动
}
}
return vHead->next;
}