[路飞]_删除排序链表中的重复元素

121 阅读2分钟

「这是我参与2022首次更文挑战的第15天,活动详情查看:2022首次更文挑战

leetcode-83 删除排序链表中的重复元素

题目介绍

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

示例1

image.png

输入: head = [1,1,2]
输出: [1,2]

示例2

image.png

输入: head = [1,1,2,3,3]
输出: [1,2,3]

提示:

  • 链表中节点数目在范围 [0, 300] 内
  • -100 <= Node.val <= 100
  • 题目数据保证链表已经按升序 排列

解题思路

此题的关键在于该链表是一个排序链表,也就是在链表中如果出现重复元素,那么重复元素将出现在该元素首次出现之后的 n 个位置。因此,我们只需要找到重复元素开始的位置,和重复元素之后第一个与重复元素不相等的元素,然后将重复元素的第一个结点的 next 指针指向重复元素之后,第一个与重复元素不相等的元素结点即可

解题步骤

  1. 如果该链表是一个空链表,直接返回空 null,也可以直接返回 head
  2. 定义指针 p 指向链表的头节点 head,定义指针 q 指向链表头节点的下一个结点 head.next
  3. q 指针没有走到链表结尾时:
  • 如果 p 指针所指向结点的值与 q 指针所指向结点的值相等,则说明 q 指针指向的结点为 p 指针指向结点的重复元素,此时 p 指针不动,q 指针继续向前走,直到 q 指针指向的结点的值与 p 指针指向的结点的值不同
  • 如果 p 指针指向结点的值与 q 指针指向结点的值不相等,则说明 q 不是 p 的重复元素,此时直接将 p 结点的 next 指针指向 q 结点,然后 pq 同时往前走一步
  1. 重复步骤 3,直到 q 指针走到链表的末尾,然后将此时 p 结点的 next 指针指向 null(如果 p 之后有重复元素,将删除 p 之后的所有元素)
  2. 返回链表的头节点 head

删除排序链表中的重复元素.gif

解题代码

var deleteDuplicates = function(head) {
    // 如果是空链表,直接返回null
    if (!head) return null
    // 定义两个指针分别指向头节点和下一个节点
    let p = head, q = head.next
    // 当q节点存在时
    while (q) {
        // 如果p的值 = q的值,q往前走一步
        if (p.val === q.val) {
            q = q.next
        } else {
            // p的值 ≠ q的值,p的下一个节点指向q
            p.next = q
            // p从q当前位置开始
            p = q
            // q从下一个节点开始
            q = q.next
        }
    }
    // 当q走到链表尾部时,直接删除p之后的节点
    p.next = null
    return head
};