开启掘金成长之旅!这是我参与「掘金日新计划 · 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);
}
}