题目描述

存在一个按升序排列的链表,给你这个链表的头节点 head ,请你删除链表中所有存在数字重复情况的节点,只保留原始链表中 没有重复出现 的数字。
返回同样按升序排列的结果链表。

示例:

No.82 删除排序链表中的重复元素②(Medium) - 图1

思路

该题需要删除所有重复的元素,一个都不保留。

递归思路

终止条件

仅有0个元素或者1个元素;

单层逻辑

传入head结点,判断head与head.next的值是否相同:
如果不同:head指向下一层递归的返回值
例如,在示例中,传入结点2,因为2和3不同,所以2到3的指向需要保留,因此是2->(3以后形成的递归返回)

如果相同:因为是排好序的链表,所以相同的值必定相邻。往后遍历,直到找到不同的值,返回该值对应的结点进行递归的返回值。
例如,在示例中,传入结点3,因为3和下一个3相同,那么一直往后找,直到找到4,返回4以后形成的递归返回。这里注意,不是直接返回4,而是4的递归返回,因为4也可能和后边结点重复。

递归代码

  1. class Solution {
  2. public ListNode deleteDuplicates(ListNode head) {
  3. // 终止条件
  4. // 没有结点或者只有一个结点了,当只有一个结点时,必然不会出现重复,直接返回该结点即可
  5. if (head == null || head.next == null) {
  6. return head;
  7. }
  8. // 相邻的两个值不同,则保留向后的指向
  9. if (head.val != head.next.val) {
  10. head.next = deleteDuplicates(head.next);
  11. return head;
  12. }
  13. // 用temp来找到不相同的结点
  14. ListNode temp = head;
  15. // 记得要加 temp != null, 否则temp.next会出现空指针异常
  16. while (temp != null && temp.val == head.val) {
  17. temp = temp.next;
  18. }
  19. // 注意不是head.next = deleteDuplicates(temp);
  20. // 因为值相同时,head.next这个引用是要丢弃的。
  21. return deleteDuplicates(temp);
  22. }
  23. }

非递归思路

定义一个tail指针用来指向当前已经形成的链表的最后一个结点,不断通过遍历后续的结点来添加不重复的结点,并且将tail重新指向最后的结点。

如果head.val == head.next.val;
head = head.next; 循环,直到找到不相等的结点,让tail 指向 head

例如:1- > 2 -> 3 -> 3 -> 4 -> 4 ->5
dummy -> 1 , tail 指向1, head指向2
dummy -> 1-> 2, tail 指向2, head指向3
dummy -> 1-> 2, tail指向2,head指向第二个3,
dummy -> 1-> 2, tail指向2,head指向第一个4,
dummy -> 1-> 2, tail指向2,head指向第二个4,
dummy -> 1 -> 2 -> 5, tail指向5,head指向5,

非递归代码

  1. class Solution {
  2. public ListNode deleteDuplicates(ListNode head) {
  3. if (head == null || head.next == null) {
  4. return head;
  5. }
  6. ListNode dummy = new ListNode(0);
  7. ListNode tail = dummy;
  8. while (head != null) {
  9. if (head.next == null || head.val != head.next.val) {
  10. tail.next = head;
  11. tail = head;
  12. }
  13. // 例如,碰到两个3的时候,循环后head指向最后一个3,但是这个3是不需要的
  14. // 因此还要在循环结束后调用head = head.next; 让其指向4
  15. while (head.next != null && head.val == head.next.val) {
  16. head = head.next;
  17. }
  18. head = head.next;
  19. }
  20. // 最后让tail指向null
  21. tail.next = null;
  22. return dummy.next;
  23. }
  24. }