一、需求
- 给定一个排序链表,删除所有重复的元素,使得每个元素只出现一次。
示例 1:
输入: 1->1->2 输出: 1->2
示例 2:
输入: 1->1->2->3->3 输出: 1->2->3
二、双指针
2.1 思路分析
- 我们定义一个头节点,它作为不含重复元素链表的头节点;
- 遍历原链表,每一次循环定位到当前重复元素最后一次出现的节点位置,将当前节点加入到新链表;
- 循环结束后,返回新链表的next即可;
- 需要注意的是:坑比较多,容易引起空指针异常;
2.2 代码实现
class Solution {
public ListNode deleteDuplicates(ListNode head) {
if(head == null || head.next == null) return head;
ListNode newHead = new ListNode(0);
ListNode p = newHead;
ListNode cur = head;
ListNode nextNode = cur.next;
while(cur != null) {
//定位到最后一次出现的重复元素
while(cur.next != null && cur.val == nextNode.val) {
cur = cur.next;
nextNode = cur.next;
}
//将最后一次出现的重复元素加入到新链表中
p.next = cur;
p = p.next;
if(cur.next == null) {
break;
}
cur = cur.next;
nextNode = cur.next;
}
return newHead.next;
}
}
2.3 复杂度分析
- 时间复杂度为O(N),其中N为链表节点的个数;
- 空间复杂度为O(1),各指针变量占用常数大小的额外空间;
三、直接法
3.1 思路分析
- 这里还有更简单的方法,在遍历链表过程中,如果遇到了重复元素,我们就更改当前节点的指向,略过与其相同的下一个元素;
3.2 代码实现
class Solution {
public ListNode deleteDuplicates(ListNode head) {
ListNode cur = head;
while(cur != null && cur.next != null) {
if(cur.val == cur.next.val) {
cur.next = cur.next.next;
} else {
cur = cur.next;
}
}
return head;
}
}
3.3 复杂度分析
- 时间复杂度为O(N);
- 空间复杂度为O(1);
四、学习地址
作者:LeetCode