学习指引
- 序、专栏前言
- 序、本章前言
- 一、【例题1】
- 1、题目描述
- 2、解题思路
- 3、模板代码
- 哈希表
- 数组哈希
- 4、代码解析
- 三、推荐专栏
- 四、课后习题
序、专栏前言
本专栏开启,目的在于帮助大家更好的掌握学习Java
,特别是一些Java学习者
难以在网上找到系统地算法学习资料帮助自身入门算法
但最最主要的还是需要独立思考,对于本专栏的所有内容,能够进行完全掌握,自己完完全全将代码写过一遍,对于算法入门肯定是没有问题的。
算法的学习肯定不能缺少总结,这里我推荐大家可以到高校算法社区将学过的知识进行打卡,以此来进行巩固以及复习。
学好算法的唯一途径那一定是题海战略,大量练习的堆积才能练就一身本领。专栏的任何题目我将会从【题目描述】【解题思路】【模板代码】【代码解析】等四板块进行讲解。
序、本章前言
哈希函数我们在第20
天查找元素时粗略提过,今天我们来提到它的另外一种使用场景。统计一个数组内每个数出现次数,很明显我们需要一个东西去存储信息,而哈希函数恰好就能帮助我们解决这个问题,而这一般也称之为计数法。以值为key
,以出现的次数为value
。像这种计数的场景,也是非常常见且重要的知识点。
一、【例题1】
1、题目描述
,然后给定
个整数
,统计每个数出现的次数并打印出来。
2、解题思路
像序章所言,我们以数值为key
,以出现的次数为value
,利用哈希函数进行存储,由于每个数的值的范围在,我们同样也可以使用数组模拟哈希表,下标替代数值,下标存储的值替代出现次数。
3、模板代码
哈希表
import java.util.*;
public class Main{
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
Map<Integer,Integer> map=new HashMap<>();
for (int i = 0; i < n; i++) {
int v=sc.nextInt();
map.put(v,map.getOrDefault(v,0)+1);
}
for (int i:map.keySet()){
System.out.println(i+"出现的次数为"+map.get(i));
}
}
}
数组哈希
import java.util.*;
public class Main{
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
int[] cnt=new int[100010];
for (int i = 0; i < n; i++) {
int v=sc.nextInt();
cnt[v]++;
}
for (int i = 0; i <=100000; i++) {
if (cnt[i]!=0){
System.out.println(i+"出现的次数为"+cnt[i]);
}
}
}
}
4、代码解析
map.keySet
函数是拿到key
的映射集,帮助我们去遍历得到所有的value
,这种循环样式在Java
中称为增强for
循环。哈希函数和数组哈希有啥区别呢?其实本质原理是相同的,不过各有优缺点,我们分别讨论一下。
哈希函数,优势在于不需要去考虑存储的
key
的值是多少,都可以直接进行存储,但由于涉及哈希碰撞以及函数调用等原因,效率肯定是不如数组哈希的。数组哈希,优势在于数组的操作效率非常高,劣势在于如果存储的值范围非常大,那就需要开一个很大的数组,空间很浪费,做题容易
MLE
,这时得需要进行配合哈希来进行离散化,这就有点本末倒置了。如果值域还存在负数,还需要进行偏移,因为数组下标没有负数。
课后习题
序号 | 题目链接 | 难度评级 |
1 | 设计哈希集合 | 1 |
2 | 设计哈希映射 | 1 |