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

608 字
3 分钟
删除排序链表中的重复元素

题目链接:83. 删除排序链表中的重复元素 - 力扣(LeetCode)

  • 难度:简单
  • 标签:链表

题目描述#

Note

原题说明: 给定一个已排序的链表的头 head , 删除所有重复的元素,使每个元素只出现一次 。返回 已排序的链表

示例 1#

graph LR A((1)) --> B((1)) --> C((2)) style A fill:#f9f,stroke:#333,stroke-width:2px style B fill:#f9f,stroke:#333,stroke-width:2px

输出[1, 2]

示例 2#

graph LR A((1)) --> B((1)) --> C((2)) --> D((3)) --> E((3))

输出[1, 2, 3]


方案:迭代指针(跳过重复项)#

核心思路: 由于链表已经排好序,重复的元素一定是相邻的。

  1. 让当前指针 cur 指向 head
  2. 比较 curcur->next 的值。
  3. 如果相等,说明找到了重复元素,让 cur->next 指向 cur->next->next(即跳过重复节点)。
  4. 如果不相等,则移动 cur 指针到下一个节点。

源码实现#

/**
* 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) return nullptr;
ListNode* cur = head;
// 当当前节点和下一个节点都存在时
while (cur && cur->next) {
if (cur->val == cur->next->val) {
// 原则:发现重复,直接跨过重复节点
cur->next = cur->next->next;
} else {
// 原则:没有重复,正常移动指针
cur = cur->next;
}
}
return head;
}
};

复杂度分析#

  • 时间复杂度O(n)O(n)。其中 nn 是链表的长度。我们只需遍历一次链表。
  • 空间复杂度O(1)O(1)。我们只使用了常数级的额外指针变量。

避坑指南:===#

Caution

血泪教训: 在编写 cur->next = cur->next->next 时,千万不要写成 cur->next == cur->next->next

  • == 是比较运算符,它不会改变指针的指向。
  • 如果写错,会导致 while 循环无法打破(或逻辑停滞),从而引发死循环。

总结#

  • 链表精髓:理解 next 指针的重新定向是链表操作的灵魂。
  • 内存安全:在实际工程中,跳过的节点(被删除的重复元素)通常需要手动释放内存(delete),但在 LeetCode 的简单题中通常不需要严苛考虑这一点。
  • 有序特性:正是因为有序,我们才只需要比较相邻节点,而不需要使用额外的哈希表来记录。
Tip

链表题目看起来花哨,但只要脑子里有一张“连线图”,代码实现往往比数组还要简洁!

文章分享

如果这篇文章对你有帮助,欢迎分享给更多人!

删除排序链表中的重复元素
https://firefly-7a0.pages.dev/posts/leetcode_notes/83remove-duplicates-from-sorted-list/
作者
lonelystar
发布于
2025-10-20
许可协议
CC BY-NC-SA 4.0
最后更新于 2025-10-20,距今已过 191 天

部分内容可能已过时

评论区

Profile Image of the Author
LonelyStar
Hello, I'm LonelyStar.
公告
欢迎来到我的博客!
音乐
封面

音乐

暂未播放

0:00 0:00
暂无歌词
分类
标签
站点统计
文章
119
分类
11
标签
346
总字数
226,548
运行时长
0
最后活动
0 天前

目录