真题描述:给定一个排序链表,删除所有重复的元素,使得每个元素只出现一次。

示例 1: 输入: 1->1->2 输出: 1->2 示例 2: 输入: 1->1->2->3->3 输出: 1->2->3

思路:将需要删除的目标结点的前驱结点 next 指针往后指一格:
链表结点的删除 - 图1

  1. /**
  2. * @param {ListNode} head
  3. * @return {ListNode}
  4. */
  5. const deleteDuplicates = function(head) {
  6. // 设定 cur 指针,初始位置为链表第一个结点
  7. let cur = head;
  8. // 遍历链表
  9. while(cur != null && cur.next != null) {
  10. // 若当前结点和它后面一个结点值相等(重复)
  11. if(cur.val === cur.next.val) {
  12. // 删除靠后的那个结点(去重)
  13. cur.next = cur.next.next;
  14. } else {
  15. // 若不重复,继续遍历
  16. cur = cur.next;
  17. }
  18. }
  19. return head;
  20. };

删除问题的延伸

真题描述:给定一个排序链表,删除所有含有重复数字的结点,只保留原始链表中 没有重复出现的数字。


示例 1: 输入: 1->2->3->3->4->4->5 输出: 1->2->5 示例 2: 输入: 1->1->1->2->3 输出: 2->3

思路:我们先来分析一下这道题和上道题有什么异同哈:相同的地方比较明显,都是删除重复元素。不同的地方在于,楼上我们删到没有重复元素就行了,可以留个“独苗”;但现在,题干要求我们只要一个元素发生了重复,就要把它彻底从链表中干掉,一个不留。

首先要做的就是定义一个 dummy 结点,指向链表的起始位置:

链表结点的删除 - 图2

这样一来,如果想要删除两个连续重复的值为 1 的结点,我们只需要把 dummy 结点的 next 指针直接指向 2:

链表结点的删除 - 图3

编码实现:

  1. /**
  2. * @param {ListNode} head
  3. * @return {ListNode}
  4. */
  5. const deleteDuplicates = function(head) {
  6. // 极端情况:0个或1个结点,则不会重复,直接返回
  7. if(!head || !head.next) {
  8. return head
  9. }
  10. // dummy 登场
  11. let dummy = new ListNode()
  12. // dummy 永远指向头结点
  13. dummy.next = head
  14. // cur 从 dummy 开始遍历
  15. let cur = dummy
  16. // 当 cur 的后面有至少两个结点时
  17. while(cur.next && cur.next.next) {
  18. // 对 cur 后面的两个结点进行比较
  19. if(cur.next.val === cur.next.next.val) {
  20. // 若值重复,则记下这个值
  21. let val = cur.next.val
  22. // 反复地排查后面的元素是否存在多次重复该值的情况
  23. while(cur.next && cur.next.val===val) {
  24. // 若有,则删除
  25. cur.next = cur.next.next
  26. }
  27. } else {
  28. // 若不重复,则正常遍历
  29. cur = cur.next
  30. }
  31. }
  32. // 返回链表的起始结点
  33. return dummy.next;
  34. };