【LeetCode刷题笔记】(十二)HashSet

137 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第32天,点击查看活动详情 这也是第45篇文章

前言

在Java中,HashSet有两大特性。

  • Hash 哈希的实现使得它搜索的时间复杂度很低。比如ArrayList<>()也有contains()方法,但是很显然HashSet的contains()方法效率更高。
  • Set Set集合中不含重复元素。这个性质可以帮助我们解决很多问题。

我们先通过一道题来引入:

141. 环形链表

题目

给你一个链表的头节点 head ,判断链表中是否有环。

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos 不作为参数进行传递 。仅仅是为了标识链表的实际情况。

如果链表中存在环 ,则返回 true 。 否则,返回 false 。

思路

如何判断链表有没有环呢?答案很简单,顺序遍历链表哦,如果出现了之前已经遍历过的元素,说明又回到了之前的点,也就是存在环,直接返回true;否则找了一圈都没找到重复的,就返回false

代码实现

public class Solution {
    public boolean hasCycle(ListNode head) {
        HashSet<ListNode> set=new HashSet<>();
        ListNode node=head;
        while(node!=null){
            if(set.contains(node)) return true;
            set.add(node);
            node=node.next;
        }
        return false;
    }
}

接下来再看另一道很有意思的题目:

无限集中的最小数字

题目

现有一个包含所有正整数的集合 [1, 2, 3, 4, 5, ...] 。

实现 SmallestInfiniteSet 类:

  • SmallestInfiniteSet() 初始化 SmallestInfiniteSet 对象以包含 所有 正整数。
  • int popSmallest() 移除 并返回该无限集中的最小整数。
  • void addBack(int num) 如果正整数 num  存在于无限集中,则将一个 num 添加 到该无限集中。

思路

我为什么说它有意思呢?因为我们完全可以反其道而行之。

既然原来的集合是无限的,那我就构造一个有限的。 收集被无限集踢掉的元素、踢掉被无限集收录的元素。

代码实现

class SmallestInfiniteSet {
    HashSet<Integer> set;
    public SmallestInfiniteSet() {
        set=new HashSet<>();
    }
    
    public int popSmallest() {
        int res=1;
        while(set.contains(res)){
            res++;
        }
        set.add(res);
        return res;
    }
    
    public void addBack(int num) {
        if(set.contains(num)) set.remove(num);
    }
}