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

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

输入:head = [1,1,1,2,3]
输出:[2,3]
提示:
- 链表中节点数目在范围
[0, 300]内 -100 <= Node.val <= 100- 题目数据保证链表已经按升序 排列
解决方案:
这段代码的核心功能是删除升序单链表中所有存在重复的节点(重复节点全部移除,而非保留一个) (比如原链表 1→2→2→3→3→3 变为 1,1→1→2→3 变为 2→3),采用「虚拟头节点 + 双层循环」实现,时间复杂度 O(n)、空间复杂度 O(1),是该进阶去重问题的经典解法。
核心逻辑
代码利用链表升序的特性,通过虚拟头节点规避头节点被删除的边界问题,再通过双层循环识别并删除所有重复节点:
- 虚拟头节点初始化 :创建虚拟头节点
node指向原链表头head,用cur指针从虚拟头节点开始遍历(避免删除原头节点时的空指针问题); - 外层循环找重复起点 :循环检查
cur的下一个和下下个节点,若二者值相等,说明存在重复节点,记录该重复值v; - 内层循环删除所有重复节点 :持续将
cur->next指向其后继节点,直到cur->next为空或值不等于v,彻底删除所有值为v的节点; - 无重复则移动指针 :若相邻节点值不相等,将
cur移动到下一个节点继续遍历; - 返回结果 :遍历完成后,返回虚拟头节点的
next(即去重后的链表头)。
总结
- 核心思路:依托升序链表重复节点相邻的特性,先识别重复值,再批量删除所有该值的节点,区别于 "保留一个重复节点" 的基础去重;
- 关键设计:虚拟头节点解决了 "头节点是重复节点需删除" 的边界问题,内层循环保证所有重复节点都被移除;
- 效率特点:一次遍历(内层循环仅为跳过重复节点,整体仍为线性遍历)完成去重,时间
O(n)、空间O(1),是该进阶去重问题的最优解法。
函数源码:
cpp/** * 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* node=new ListNode(); node->next=head; ListNode* cur=node; int v=0; while(cur->next && cur->next->next){ v=cur->next->val; if(v==cur->next->next->val){ while(cur->next && v==cur->next->val){ cur->next=cur->next->next; } }else{ cur=cur->next; } } return node->next; } };