一日一练: 删除链表中的重复元素

106 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第10天,点击查看活动详情

1. 删除链表中的重复元素-1

给定一个已排序的链表的头 head , 删除所有重复的元素,使每个元素只出现一次 。返回 已排序的链表 。

删除已排序链表的重复元素。这道题的思路比较简单:从头开始,比较当前节点与下一个节点的值是否相同,相同的话删除下一个节点(删除操作☞这篇文章里有详细说明),不同的话,指针指向下一个节点

function deleteDuplicates(head: ListNode | null): ListNode | null {
  let cur = head
  // 比较当前节点与下一个节点的值
  while(cur && cur.next) {
      // 相同的话删除下一个节点
      if (cur.val === cur.next.val) {
          cur.next = cur.next.next
      } else {
      // 不同的话,cur指向下一个节点
          cur = cur.next
      }
  }
  // 不会改变头节点
  return head
};
  • 时间复杂度:O(n),n是链表长度
  • 空间复杂度: O(1)

2 删除链表中的重复元素-2

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

这道理与1中的题不同点在于: 只要有重复节点,把所有节点都删除了。

    1. 因为有可能头结点被删除,所以需要哨兵节点
    1. head开始,比较与下一个节点的值是否相同
    • 相同的话,保存当前val,然后循环往后找到第一个值不为val的节点
      • 有相同的值,就删除当前节点
      • 找到不同的值,跳出找值的循环,继续外层比较
    • 不同的话,移动指针继续比较
function deleteDuplicates(head: ListNode | null): ListNode | null {
    const dummy = new ListNode(-1, head)
    let pre = dummy
    let cur = head
    while(cur) {
        // 找到 值与下一个节点值 相同的节点
        if (cur.next && cur.val === cur.next.val) {
            let val = cur.val
            // 循环找第一个值不为val的节点
            while(cur && val === cur.val) {
                // 值相同的话,删除cur,同时cur -> cur.next
                cur = pre.next = cur.next
            }
        } else {
            // 移动指针,继续找
            pre = pre.next
            cur = cur.next
        }
    }
    return dummy.next
};
  • 时间复杂度: 虽然有两个while循环,但是只扫描了一次,O(n),n是链表长度
  • 空间复杂度: O(1)