day140—前后指针—删除排序链表中的重复元素Ⅱ(LeetCode-82)

题目描述

给定一个已排序的链表的头 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),是该进阶去重问题的经典解法。

核心逻辑

代码利用链表升序的特性,通过虚拟头节点规避头节点被删除的边界问题,再通过双层循环识别并删除所有重复节点:

  1. 虚拟头节点初始化 :创建虚拟头节点 node 指向原链表头 head,用 cur 指针从虚拟头节点开始遍历(避免删除原头节点时的空指针问题);
  2. 外层循环找重复起点 :循环检查 cur 的下一个和下下个节点,若二者值相等,说明存在重复节点,记录该重复值 v
  3. 内层循环删除所有重复节点 :持续将 cur->next 指向其后继节点,直到 cur->next 为空或值不等于 v,彻底删除所有值为 v 的节点;
  4. 无重复则移动指针 :若相邻节点值不相等,将 cur 移动到下一个节点继续遍历;
  5. 返回结果 :遍历完成后,返回虚拟头节点的 next(即去重后的链表头)。

总结

  1. 核心思路:依托升序链表重复节点相邻的特性,先识别重复值,再批量删除所有该值的节点,区别于 "保留一个重复节点" 的基础去重;
  2. 关键设计:虚拟头节点解决了 "头节点是重复节点需删除" 的边界问题,内层循环保证所有重复节点都被移除;
  3. 效率特点:一次遍历(内层循环仅为跳过重复节点,整体仍为线性遍历)完成去重,时间 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;
    }
};
相关推荐
小尧嵌入式2 小时前
【Linux开发一】类间相互使用|继承类和构造写法|虚函数实现多态|五子棋游戏|整数相除混合小数|括号使用|最长问题
开发语言·c++·算法·游戏
Remember_9932 小时前
【JavaSE】一站式掌握Java面向对象编程:从类与对象到继承、多态、抽象与接口
java·开发语言·数据结构·ide·git·leetcode·eclipse
皮蛋sol周2 小时前
嵌入式学习数据结构(二)双向链表 内核链表
linux·数据结构·学习·嵌入式·arm·双向链表
BHXDML2 小时前
第三章:聚类算法
算法·机器学习·聚类
仙俊红2 小时前
二分查找边界模板:第一个 > target / 第一个 < target(找不到就返回边界)
算法
苦藤新鸡2 小时前
16.求数组除了当前元素的所有乘积
算法·leetcode·动态规划
Benny_Tang2 小时前
题解:P14841 [THUPC 2026 初赛] 哈姆星与古地球学术行为影响星球文明的考古学分析
c++·算法
WilliamHu.2 小时前
A2A协议
java·数据结构·算法
Tisfy2 小时前
LeetCode 1895.最大的幻方:暴力中来点前缀和优化
算法·leetcode·前缀和·矩阵·题解·暴力