27-删除升序链表中的重复元素II

image-20210506191316234

自己的做法

算法思想

因为有可能头节点是重复节点,所以方便删除,可以添加一个哨兵节点,即在头节点前再添加一个节点。

设置计数变量count,初始为1,如果有重复节点,则count >= 2。

设置pre指向访问过程中已知的最后一个不重复的节点,初始指向哨兵节点。

设置cur指针来遍历节点,初始指向头节点。

遍历链表,当当前链表的下个节点的值和当前节点的值相等时,就访问下个节点。同时计数变量count 加1。

如果不相等,有两种情况:

  1. count为1,说明不是重复节点,则将pre指向cur指向的节点,即pre = cur,同时cur访问下一个节点
  2. count不为1,则说明是重复节点,应该删除。则令pre的next指向cur的next,同时计数变量重新置为1,并访问下个节点

注:(pre, cur]之间的为重复的节点,不包括pre,包括cur。

算法实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Solution {
public:
static ListNode* deleteDuplicates(ListNode* head) {
if(head == nullptr || head->next == nullptr) {return head;}
ListNode * sentinel = new ListNode();
sentinel->next = head;
ListNode * pre = sentinel;
ListNode * cur = head;
int count = 1;
while (cur) {
if(cur->next && cur->next->val == cur->val) {
count++;
} else {
if(count != 1) {
pre->next = cur->next;
count = 1;
} else {
pre = cur;
}
}
cur = cur->next;

}
return sentinel->next;

}
};

性能分析

时间复杂度:遍历一遍链表,O(n)O(n)

空间复杂度:O(1)O(1)

参考做法

算法思想

设置一个哑结点(dummy node,其实和哨兵节点一样,就是在头节点前加一个节点)。

设置指针cur,初始指向哑结点,然后判断cur->next和cur->next->next的值是否相等,

如果相等,那么就记录下该值x,并循环删除cur->next及其后面所有和x相等的值,直到cur->next为空或cur->next的值和x不相等;

如果不相等,那么就cur就指向下一个节点。

算法实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Solution {
public:
static ListNode* deleteDuplicates(ListNode* head) {
if(head == nullptr || head->next == nullptr) {return head;}
ListNode * dummy = new ListNode();
dummy->next = head;
ListNode * cur = dummy;
while (cur->next && cur->next->next) {
if(cur->next->val == cur->next->next->val) {
int x = cur->next->val;
while (cur->next || cur->next->val == x) {
cur->next = cur->next->next;
}
} else {
cur = cur->next;
}
}
return dummy->next;

}
};

性能分析

时间复杂度:O(n)O(n)

空间复杂度:O(1)O(1)

注:如果只是做题,可以不释放删除节点的内存,但在实际工作中,一定是要释放的。


27-删除升序链表中的重复元素II
https://zhaoquaner.github.io/2022/05/11/leetcode/链表/27-删除升序链表中的重复元素II/
更新于
2022年5月22日
许可协议