【算法--链表】83.删除排序链表中的重复元素--通俗讲解
一、题目是啥?一句话说清
给你一个已经排序的链表,删除所有重复的元素,使得每个元素只出现一次,并返回处理后的链表。
示例:
- 输入:1 → 1 → 2 → 3 → 3
- 输出:1 → 2 → 3
二、解题核心
利用链表已排序的特性,遍历链表,比较当前节点与下一个节点的值,如果相同就跳过下一个节点,否则移动到下一个节点。 这就像处理一排已经按身高排序的队伍,如果发现相邻两个人身高相同,就让后一个人离开队伍。
三、关键在哪里?(3个核心点)
想理解并解决这道题,必须抓住以下三个关键点:
1. 利用已排序的特性
- 是什么:因为链表已经排序,所有重复元素一定是相邻的。
- 为什么重要:这样只需要一次遍历就能删除所有重复元素,不需要使用额外数据结构(如哈希表)来记录已出现的元素。
2. 指针操作
- 是什么:使用一个指针遍历链表,比较当前节点与下一个节点的值。
- 为什么重要:通过调整指针的指向来"跳过"重复节点,而不是实际删除节点(在C++中需要注意内存管理,但算法题通常更关注逻辑)。
3. 边界条件处理
- 是什么:处理空链表或单节点链表的情况。
- 为什么重要:这些特殊情况不需要任何操作,直接返回即可,避免程序出错。
四、看图理解流程(通俗理解版本)
让我们用链表 1 → 1 → 2 → 3 → 3 的例子来可视化过程:
-
初始化:
- 设置当前指针
curr
指向头节点 1。 - 链表状态:1 → 1 → 2 → 3 → 3
- 设置当前指针
-
第一轮比较:
- 比较
curr.val
(1) 和curr.next.val
(1),两者相等。 - 跳过下一个节点:让
curr.next
指向curr.next.next
(即第二个1指向2)。 - 链表状态:1 → 2 → 3 → 3
curr
仍然指向第一个1(因为可能还有重复)。
- 比较
-
第二轮比较:
- 再次比较
curr.val
(1) 和curr.next.val
(2),两者不相等。 - 移动
curr
到下一个节点(指向2)。 - 链表状态:1 → 2 → 3 → 3
- 再次比较
-
第三轮比较:
- 比较
curr.val
(2) 和curr.next.val
(3),两者不相等。 - 移动
curr
到下一个节点(指向3)。 - 链表状态:1 → 2 → 3 → 3
- 比较
-
第四轮比较:
- 比较
curr.val
(3) 和curr.next.val
(3),两者相等。 - 跳过下一个节点:让
curr.next
指向curr.next.next
(即null)。 - 链表状态:1 → 2 → 3
curr
仍然指向3。
- 比较
-
结束:
curr.next
为null,循环结束。- 返回头节点1。
五、C++ 代码实现(附详细注释)
#include <