🚩传送门:牛客题目

题目

给出一个升序排序的链表,删除链表中的所有重复出现的元素,只保留原链表中只出现一次的元素。
例如:
给出的链表为 [NC]24. 删除有序链表中重复的元素-II - 图1, 返回 [NC]24. 删除有序链表中重复的元素-II - 图2
给出的链表为 [NC]24. 删除有序链表中重复的元素-II - 图3 , 返回 [NC]24. 删除有序链表中重复的元素-II - 图4

数据范围:链表长度 0≤n≤10000,链表中的值满足 ∣val∣≤1000
要求:空间复杂度 O(n),时间复杂度 O(n)
进阶:空间复杂度 O(1),时间复杂度 O(n)

示例1

输入:{1,2,2} 返回值:{1}

示例2

输入:{} 返回值:{}

解题思路:一次遍历

由于给定的链表是排好序的,因此重复的元素在链表中出现的位置是连续的,因此只需要对链表进行一次遍历,就可以删除重复的元素。由于链表的头节点可能会被删除,因此我们需要额外使用一个哑节点dummy node)指向链表的头节点。

  • pre 指向已经处理后未重复部分的末尾结点,
  • cur 指向当前判断结点
  • next 指向当前判断结点的下一个结点

    nextcur 值相等,则 next 后移 **next=next.next** 直至 next=null 或者值不等于 cur 此时将 **pre.next=next** 删除所有重复的红色部分

    nextcur 值不等,则 pre ,cur ,next 依次后移

当遍历完整个链表之后,我们返回链表的的哑节点的下一个节点 dummy.next 即可。
image.png

复杂度分析

时间复杂度: [NC]24. 删除有序链表中重复的元素-II - 图6 ,其中 [NC]24. 删除有序链表中重复的元素-II - 图7 是链表的长度。

空间复杂度:[NC]24. 删除有序链表中重复的元素-II - 图8

🚩我的代码

  1. public ListNode deleteDuplicates (ListNode head) {
  2. // 判空
  3. if(head==null)return head;
  4. // 初始化
  5. ListNode dump=new ListNode(-1,head);
  6. ListNode pre=dump;
  7. ListNode cur=head;
  8. ListNode next=head.next;
  9. // 处理直至结尾
  10. while(next!=null){
  11. // 若相等
  12. if(cur.val==next.val){
  13. // 直至 next=null 或者值不等于 cur
  14. while(next!=null&&next.val==cur.val)next=next.next;
  15. // 舍弃红色的重复部分
  16. pre.next=next;
  17. cur=next;
  18. next=(next==null?null:next.next);
  19. }
  20. else{ // 不等,指针依次后移
  21. pre=cur;
  22. cur=next;
  23. next=next.next;
  24. }
  25. }
  26. return dump.next;
  27. }

官方代码

  1. public ListNode deleteDuplicates(ListNode head) {
  2. // 判空
  3. if (head == null) return head;
  4. // 头结点
  5. ListNode dummy = new ListNode(0, head);
  6. ListNode cur = dummy;
  7. while (cur.next != null && cur.next.next != null) {
  8. if (cur.next.val == cur.next.next.val) {
  9. int x = cur.next.val;
  10. while (cur.next != null && cur.next.val == x) {
  11. cur.next = cur.next.next;
  12. }
  13. } else {
  14. cur = cur.next;
  15. }
  16. }
  17. return dummy.next;
  18. }