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

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

1 2
| 输入:head = [1,1,1,2,3] 输出:[2,3]
|
提示:
- 链表中节点数目在范围
[0, 300] 内
-100 <= Node.val <= 100
- 题目数据保证链表已经按升序 排列
实现代码
方式一:链表分解
通过将链表分解为重复元素链表和不重复元素链表,最终返回不重复链表即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
|
class Solution { public ListNode deleteDuplicates(ListNode head) {
ListNode p1 = new ListNode(101), pp1 = p1, p2 = new ListNode(101), pp2 = p2, p = head; while(p != null){ if(p.next != null && p.val == p.next.val || p.val == pp1.val){ pp1.next = p; pp1 = pp1.next; }else{ pp2.next = p; pp2 = pp2.next; } p = p.next; } pp1.next = null; pp2.next = null; return p2.next; } }
|
核心点
ListNode p1 = new ListNode(101), p2 = new ListNode(101):存放重复元素与不重复元素,val = 101是为了不影响重复元素判断;
p.val == pp1.val:用于过滤掉重复元素;
pp1.next = null; pp2.next = null;:用于断开原链表,分解链表一定要与旧链表断开;
时间复杂度
O(n)
空间复杂度
O(1)
方式二:双指针
使用双指针方式,定义虚拟节点q和索引指针p、p1,p1向前移的同时始终校验前面节点是否相同,相同则一直往前移动直到遇到不同节点,否则将当前节点链虚拟节点上;
难点:如何断定两个节点不相等并且不是重复节点?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
|
class Solution { public ListNode deleteDuplicates(ListNode head) {
ListNode q = new ListNode(-1), p = q; ListNode p1 = head; while (p1 != null) { if (p1.next != null && p1.val == p1.next.val) { while (p1.next != null && p1.val == p1.next.val) { p1 = p1.next; } p1 = p1.next; continue; } p.next = p1; p1 = p1.next; p = p.next; } p.next = null; return q.next; } }
|
时间复杂度
链表长度O(n)
空间复杂度
O(1)