文章目录
题目
标题和出处
标题:删除排序链表中的重复元素 II
出处:82. 删除排序链表中的重复元素 II
难度
4 级
题目描述
要求
给你一个按升序排列的链表的头节点 head \texttt{head} head,请你删除链表中所有存在数字重复情况的结点,只保留原始链表中没有重复出现的数字。
返回同样按升序排列的结果链表。
示例
示例 1:
输入:
head
=
[1,2,3,3,4,4,5]
\texttt{head = [1,2,3,3,4,4,5]}
head = [1,2,3,3,4,4,5]
输出:
[1,2,5]
\texttt{[1,2,5]}
[1,2,5]
示例 2:
输入:
head
=
[1,1,1,2,3]
\texttt{head = [1,1,1,2,3]}
head = [1,1,1,2,3]
输出:
[2,3]
\texttt{[2,3]}
[2,3]
数据范围
- 链表中的结点数目在范围 [0, 300] \texttt{[0, 300]} [0, 300] 内
- -100 ≤ Node.val ≤ 100 \texttt{-100} \le \texttt{Node.val} \le \texttt{100} -100≤Node.val≤100
- 题目数据保证链表已经按升序排列
解法
思路和算法
这道题是「删除排序链表中的重复元素」的进阶,要求只保留原始链表中没有重复出现的数字。
由于原始链表的头结点的值可能在原始链表中重复出现,因此原始链表的头结点可能要被删除,需要创建哑节点 dummyHead \textit{dummyHead} dummyHead,令 dummyHead . next = head \textit{dummyHead}.\textit{next} = \textit{head} dummyHead.next=head。
从 dummyHead \textit{dummyHead} dummyHead 开始遍历链表,用 curr \textit{curr} curr 表示遍历到的结点,则下一个结点是 next = curr . next \textit{next} = \textit{curr}.\textit{next} next=curr.next。当 curr \textit{curr} curr 没有到达尾结点时,需要判断 next \textit{next} next 的后面是否有值相同的结点,以此决定 next \textit{next} next 和它后面的结点是否需要删除。具体做法如下:
-
如果 next \textit{next} next 是尾结点,或者 next \textit{next} next 和它后面的结点的值不同,则 next \textit{next} next 不需要删除,将 curr \textit{curr} curr 向后移动一步;
-
如果 next \textit{next} next 和它后面的结点的值相同,则需要将 next \textit{next} next 后面具有相同值的结点全部删除,然后将 next \textit{next} next 删除。
-
删除 next \textit{next} next 后面具有相同值的结点时,令 next . next : = next . next . next \textit{next}.\textit{next} := \textit{next}.\textit{next}.\textit{next} next.next:=next.next.next,直到 next . next \textit{next}.\textit{next} next.next 变成空节点或者 next . next . val ≠ next . val \textit{next}.\textit{next}.\textit{val} \ne \textit{next}.\textit{val} next.next.val=next.val;
-
删除 next \textit{next} next 时,令 curr . next : = next . next \textit{curr}.\textit{next} := \textit{next}.\textit{next} curr.next:=next.next。
-
当 curr \textit{curr} curr 到达尾结点时,遍历结束。新链表的头结点为 dummyHead . next \textit{dummyHead}.\textit{next} dummyHead.next。
代码
class Solution {
public ListNode deleteDuplicates(ListNode head) {
ListNode dummyHead = new ListNode(0);
dummyHead.next = head;
ListNode curr = dummyHead;
while (curr.next != null) {
ListNode next = curr.next;
if (next.next == null || next.next.val != next.val) {
curr = curr.next;
} else {
while (next.next != null && next.next.val == next.val) {
next.next = next.next.next;
}
curr.next = next.next;
}
}
return dummyHead.next;
}
}
复杂度分析
-
时间复杂度: O ( n ) O(n) O(n),其中 n n n 是链表的长度。需要遍历链表一次,删除重复元素,对于每个元素的操作时间都是 O ( 1 ) O(1) O(1)。
-
空间复杂度: O ( 1 ) O(1) O(1)。