题目描述
给定一个升序排序的链表,删除链表中的所有重复出现的元素,只保留原链表中只出现一次的元素。
示例
示例 1
输入:
1 → 2 → 3 → 3 → 4 → 4 → 5
返回:
1 → 2 → 5
示例 2
输入:
1 → 1 → 1 → 2 → 3
返回:
2 → 3
数据范围
- 链表长度: 0 ≤ n ≤ 10000 0 \leq n \leq 10000 0≤n≤10000
- 链表中的值满足 ∣ v a l ∣ ≤ 1000 |val| \leq 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)
解题思路
我们需要遍历链表并删除所有重复出现的元素。由于链表是升序排序的,因此可以利用这个特点进行优化,处理的方式是利用两个指针(pre
和 cur
)遍历链表,pre
指向处理后的最后一个节点,cur
指向当前遍历的节点。
具体的做法是:
- 当当前节点的值不等于下一个节点的值时,将
pre
指向当前节点,cur
指向下一个节点。 - 当当前节点的值等于下一个节点的值时,跳过所有重复的节点,直到找到一个新的不同值的节点,并将
pre
的next
指向这个节点。
这种方法可以实现一次遍历完成,时间复杂度为 O ( n ) O(n) O(n),空间复杂度为 O ( 1 ) O(1) O(1)(不考虑递归栈的空间)。
代码实现
/**
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
/**
* 删除有序链表中重复的元素,只保留出现一次的元素
*
* @param head ListNode类
* @return ListNode类
*/
struct ListNode* deleteDuplicates(struct ListNode* head) {
// 如果链表为空或只有一个元素,直接返回
if (head == NULL || head->next == NULL)
return head;
// 创建一个虚拟头节点,方便处理头节点的删除
struct ListNode* dummy = (struct ListNode*) malloc(sizeof(struct ListNode));
dummy->next = head;
struct ListNode* pre = dummy; // pre指向虚拟头节点
struct ListNode* cur = head; // cur指向当前节点
while (cur != NULL) {
// 如果当前节点的值不等于下一个节点的值,正常移动
if (cur->next == NULL || cur->val != cur->next->val) {
pre = pre->next; // 更新pre
cur = cur->next; // 更新cur
} else {
// 如果当前节点的值等于下一个节点的值,跳过重复节点
while (cur->next != NULL && cur->val == cur->next->val) {
cur = cur->next; // 跳过所有重复节点
}
pre->next = cur->next; // 将pre的next指向当前节点的下一个节点
cur = cur->next; // 更新cur
}
}
return dummy->next; // 返回去除虚拟头节点后的链表
}
代码解释
-
链表为空或只有一个元素时,直接返回原链表,因为不需要进行任何处理。
-
创建虚拟头节点,
dummy
节点用于处理链表的头节点情况。pre
指向虚拟头节点,cur
指向链表的第一个节点。 -
遍历链表:
- 如果当前节点与下一个节点的值不同,说明当前节点没有重复值,我们可以将
pre
更新为cur
,然后移动cur
到下一个节点。 - 如果当前节点与下一个节点的值相同,说明有重复节点,我们需要跳过所有相同的节点,将
pre->next
指向当前节点的下一个不同值的节点,直到找到新的值。
- 如果当前节点与下一个节点的值不同,说明当前节点没有重复值,我们可以将
-
返回虚拟头节点的
next
指针,即去除重复元素后的链表。
复杂度分析
-
时间复杂度:每个节点最多被访问两次(一次正常遍历,另一次跳过重复节点),因此时间复杂度为 O ( n ) O(n) O(n),其中 n n n是链表的长度。
-
空间复杂度:除了返回的链表外,我们只用了常数空间(
dummy
,pre
,cur
)。因此,空间复杂度为 O ( 1 ) O(1) O(1)。