leetcode刷题题解——面试题 02.01. 移除重复节点

本文探讨了一种解决链表中重复节点问题的算法,主要讲解了暴力解法的时间复杂度问题,以及如何利用哈希表(如HashMap和HashSet)以O(1)的时间复杂度提高效率。提供了两种Java实现,分别使用HashMap和HashSet,对比了两者在实际应用中的差异。
摘要由CSDN通过智能技术生成

面试题 02.01. 移除重复节点

题目

编写代码,移除未排序链表中的重复节点。保留最开始出现的节点。

示例1:

  • 输入:[1, 2, 3, 3, 2, 1]
  • 输出:[1, 2, 3]

示例2:

  • 输入:[1, 1, 1, 1, 2]
  • 输出:[1, 2]

提示:
链表长度在[0, 20000]范围内。
链表元素在[0, 20000]范围内。

思路

暴力解法

  1. 从前面每个节点开始,与后面的每个节点进行比较,从而进行重复元素的移除,如下:
    在这里插入图片描述
    但是显然时间复杂度为O( n 2 n^2 n2)
  2. 利用数组存储已访问节点,然后遇到下一个节点时判断是否在已访问数组中,当前数组可以用List来替代,同时使用contain方法判断是否该节点已访问,但是contain方法也是一个时间复杂度为O( n n n)的函数,所以该思路复杂度依旧为O( n 2 n^2 n2)

哈希表

利用哈希表来保存已访问数组,并使用map.get(p.next.val)!=null判断该节点是否存在哈希表中,可能有同学会有疑惑,为什么同样是存储已访问的值,但是哈希表却优于数组、List,其中主要是通过哈希函数的哈希映射能够以远小于O( n n n)的时间复杂度找到该节点,更甚者时间复杂度为O(1)。至于这方面的知识我就不展开来说,毕竟包含的知识点太多了

Java实现

我自己写的

class Solution {
    public ListNode removeDuplicateNodes(ListNode head) {
        Map<Integer,Boolean> map = new HashMap<>();
        if (head==null||head.next==null) return head;
        ListNode p = head;
        map.put(p.val,Boolean.TRUE);
        while (p!=null&&p.next!=null){
            if (map.get(p.next.val)!=null) p.next = p.next.next;
            else {
                map.put(p.next.val,Boolean.TRUE);
                p = p.next;   
            }
        }
        return head;
    }
}

leetcode官方题解

为什么我会把官方的题解贴在这里,其实主要是刚好有个对照,同学们认真看,可以看到我的答案中使用的是HashMap,而官方题解使用的是HashSet,这其中有什么关系呢?其实它们都是哈希表,这个也是我一开始没有想到的,但是实质上,在这里确实是HashSet更好。在我的代码中,其实大家可以发现,判断哈希表中是否已存在该元素,我使用的是map.get(p.next.val)!=null,所以其实我存储的值是没有意义的。而在官方题解中,则是判断元素是否添加成功来判断哈希表是否存在该元素。显然,这灵活地运用了add函数的返回值,为什么返回值为false,那还不是已经存在该元素了吗?

class Solution {
    public ListNode removeDuplicateNodes(ListNode head) {
        if (head == null) {
            return head;
        }
        Set<Integer> occurred = new HashSet<Integer>();
        occurred.add(head.val);
        ListNode pos = head;
        // 枚举前驱节点
        while (pos.next != null) {
            // 当前待删除节点
            ListNode cur = pos.next;
            if (occurred.add(cur.val)) {
                pos = pos.next;
            } else {
                pos.next = pos.next.next;
            }
        }
        pos.next = null;
        return head;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

绿豆蛙给生活加点甜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值