注释已经详细给出了 时间复杂度O(n) 空间复杂度O(1)

补充:无序时使用哈希表统计各数值出现次数,仅保留出现次数为1的结点

对比:算法比官方复杂一点,但是考虑到了内存泄漏的问题,面试时可以询问是否删除结点依次选择算法

/**
 * struct ListNode {
 *	int val;
 *	struct ListNode *next;
 * };
 */

class Solution {
public:
    ListNode* deleteDuplicates(ListNode* head) {
      if (head == nullptr || head->next == nullptr) {
        return head;
      }
      
      // 首元结点可以解决第一个元素就是重复的情况
      ListNode *head_node = new ListNode(-1);
      head_node->next = head;
      
      // 三个结点:pre指向的结点绝对不会和cur重复,cur和nex用来删除重复结点
      ListNode *pre = head_node, *cur = head, *nex = head->next;
      
      while (nex) {
          // 不重复则整体往前挪动,一次只能挪动一格,防止nex和nex->是重复元素
        if (cur->val != nex->val) {
          pre = cur;
          cur = nex;
          nex = nex->next;
        } else {
          // 重复有两种情况:只有两个重复 | 有多个重复
          // 重复则找出这个重复子链表,不断删除直到剩下两个重复元素
          while (nex->next && nex->next->val == cur->val) {
            nex = nex->next;
          }
          while (cur->next != nex) {
            ListNode *tmp = cur;
            cur = cur->next;
            delete(tmp);
          }
          // 两个while处理后,只剩下两个重复元素这一种情况
          pre->next = nex->next;
          delete(cur);
          delete(nex);
          // 考虑最后两个元素重复的情况
          if (pre->next == nullptr) {
            break;
          }
          // 移动指针
          cur = pre->next;
          nex = cur->next;
        }
      }
      
      head = head_node->next;
      delete(head_node);
      
      return head;
    }
};