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

227 阅读1分钟

Offer 驾到,掘友接招!我正在参与2022春招系列活动-刷题打卡任务,点击查看活动详情

一、题目

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

  示例 1:

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

示例 2:

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

提示:

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

二、题解

1.解读

要删除重复的节点并且链表已经有序了,那么节点值相同的节点都是相邻连续的,所有只要一次遍历链表节点,找到相同的节点值删除多余的节点即可,注意的是重复的节点不需要保留一个,是需要删除所有重复的节点。

方法一

可以两两比较一个节点与后面一个节点的值是否相同来判断重复元素,首先需要给head链表前额外加一个头结点pre,然后再用一个指针cur指向这个链表头结点处,之后就移动指针遍历链表节点。定义v变量为当前指针curnext节点的值,如果v的值与当前指针curnext节点的next节点值不相等,说明这当前curnext节点不存在重复的节点,就cur = cur.next跳过这个节点继续判断之后的节点;否则发现当前指针curnext节点和其后一个节点的值相同,那就需要把这相同的节点删除,同时相同的节点可能不止这两个,所以要一并将其之后可能存在若干的相同值的节点都删除。一个小循环判断如果当前cur还有next节点并且该节点的下一个节点值等于v,那么就需要删除cur.next = cur.next.next,直到指针cur之后没有节点或者cur.next之后节点值不重复了就结束删除重复节点,如果后面还有节点就继续查找重复节点删除重复节点的操作,最后返回最初添加的头结点pre之后的next节点即可。

三、代码 方法一 Java代码

class Solution {
    public ListNode deleteDuplicates(ListNode head) {
        if (head == null) {
            return null;
        }
        ListNode pre = new ListNode(0, head);
        ListNode cur = pre;
        while (cur.next != null && cur.next.next != null) {
            int v = cur.next.val;
            if (v != cur.next.next.val) {
                cur = cur.next;
                continue;
            }
            while (cur.next != null && cur.next.val == v) {
                cur.next = cur.next.next;
            }
        }
        return pre.next;
    }
}

时间复杂度:O(n),需要遍历一次链表。

空间复杂度:O(1),需要参数个空间变量。

四、总结

初始的head的头结点可能是应该要删除的所有在其之前添加一个节点方便处理,两两比较的话要注意判断这些节点是否存在,避免NPE。