Leetcode:链表——删除有序链表中的重复元素

原题链接:82. 删除排序链表中的重复元素 II - 力扣(LeetCode)

思路

本题中给出的链表已经是有序的了,因此重复的元素是连续一起出现的,并且可能会出现不同的重复元素,例如:1,2,3,3,4,4,5 。并且我们还需要判断头节点是否被删除了的特殊情况。

我们采用如下做法:当出现重复元素时,我们直接遍历到重复元素中的最后一个,然后一次性把所有重复元素一并删除,直接将上一个不为重复的元素的 next 域指向下一个不重复的元素。例如:

当链表中元素依次为 1,2,2,2,3 时,我们先定义一个变量 cur 来遍历链表,当 cur 来到节点1时,发现 cur.next 和 cur.next.next 的值都为 2 ,那么就说明 2 是重复元素,但是我们此时不知道接下去有多少个 2 ,因此我们再定义一个节点 node ,将其初始化为 cur.next.next,也就是重复出现的第二个 2 ,然后让其遍历链表寻找链表中的最后一个 2 ,当 node 来到第三个 2 时,就会发现它的下一个节点已经是 3 ,不是重复元素了,那么就让 node 停下来,它的使命已经完成了。

此时我们发现,node.next 就是继 cur(cur 为 1 ) 之后的下一个不为重复的元素,因此直接将 cur的下一个节点指向该节点即可,即:cur.next = node.next,此举过后,1 的下一个节点就直接变成了 3 ,一次性将链表中出现的三个 2 都删除了。

图示:

1)

2)

3)

4) 

注意点

1)node 在遍历之前,还需要判断 node 是否是链表中的最后一个节点,即:node.next是否为 null ,否则在比较 node 的值和 node.next 的值的时候会出现空指针异常;

2)当使用 cur 遍历链表时,如果遇到重复元素,就进行删除,但无需往后走;当遇到不重复的元素时,才需要往后走;(cur = cur.next)

3)使用 cur 遍历链表时,由于循环内部我们需要使用到 cur.next.next,因此循环条件处需要对cur.next.next 进行判空。除此之后,还需要对 cur.next 进行判空。这是因为:当删除了的重复元素刚好是链表中的最后一个元素时,即 node.next = null,那么此时 cur.next = node.next,即为 cur.next = null,因此如果此时不对 cur.next 判空,cur.next.next 就会出现空指针异常.并且对 cur.next 的判断还需要放在对 cur.next.next 的判断之前,先后顺序不能改变,否则 cur.next 判空就判了个寂寞;

4)为了解决头节点可能就是重复元素而被删除了,因此删除的时候,我们还需要判断 cur.next 是不是头节点。由此我们也可以得出 cur 应该初始化为哑节点,即 cur.next = head。

class Solution {
    public ListNode deleteDuplicates(ListNode head) {
        if(head == null || head.next == null) {
            return head;
        }

        ListNode cur = new ListNode(0, head);

        //当删除完重复节点后,cur刚好是最后一个节点时,此时cur.next为空
        //其他一般情况下,需对cur.next.next进行判空
        //对cur.next的判空必须放在&&前面,否则会出现cur.next.next空指针异常
        while(cur.next != null && cur.next.next != null) {
            if(cur.next.val == cur.next.next.val) {
                //找到重复节点中的最后一个节点
                ListNode node = cur.next.next;
                //进行循环前,需要判断node是否是链表中最后一个节点且必须放在&&前面判断
                //否则会出现node.next空指针异常
                while(node.next != null && node.val == node.next.val) {
                    node = node.next;
                }
                //判断是否删除了头节点
                if(cur.next == head) {
                    head = node.next;
                }
                //此时node为最后一个重复的节点,其下一个节点就是不重复的第一个节点
                cur.next = node.next;
            }else {
                cur = cur.next;
            }
        }

        return head;
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值