33. 删除排序链表中的重复元素 II 【LC82】

175 阅读2分钟

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

image.png

关键思路:

因为要连接前后节点,所以需要记录父节点,父指针初始指向null;

遍历所有的节点:

  • 判断当前节点的真实后序节点与符合要求的后续节点是否是一个节点;
    • 如果是一个节点,
      • 如果是链表头,则令父指针指向当前节点;
      • 如果不是链表头,且父节点的next不为当前节点的情况下,重连一下父节点和当前节点,为什么会出现这个情况呢?因为next !== cur.next的情况时无法处理父指针。令父指针指向当前节点
    • 如果不是一个节点,则不处理父指针,因为无法预知下面是否符合条件
      • 如果父指针为空,则表示去重节点在链表头,这种情况直接head重新指向到next,直接后移;
      • 如果父指针不为空,则说明不是链表头,直接后移;

小伙伴们能理解这个思路不?

解:

var deleteDuplicates = function (head) {
  if (!head || !head.next) {
    return head;
  }
  let parantCur = null;
  let cur = head;
  let next = null;
  while (cur) {
    next = cur.next
    while (next && cur.val === next.val) {
      next = next.next
    }

    if (cur.next === next) { //当前节点的下一个节点和去重后下一个节点是同一个节点
      if (parantCur && parantCur.next !== cur) { // 分情况讨论,是不是链表头
        parantCur.next = cur // 不是的情况,重连至当前节点, 也不是所有都需要重新连接,parent.next !== cur的时候重连,其他的时候保持连接
      }
      parantCur = cur // 重置父指针是cur,下一轮cur的父节点
    } else { //当前节点的下一个节点和去重后下一个节点不是同一个节点
      if (!parantCur) { // 链表头
        head = next;
      }
    }
    cur = next
  }
  parantCur && (parantCur.next = next);
  return head;
};