【第25天】给定一个长度为 n 的数组,统计每个数出现的次数 | 计数哈希

本文已收录于专栏
《Java入门一百例》

学习指引

  • 序、专栏前言
  • 序、本章前言
  • 一、【例题1】
    • 1、题目描述
    • 2、解题思路
  • 3、模板代码
      • 哈希表
      • 数组哈希
    • 4、代码解析
  • 三、推荐专栏
  • 四、课后习题

序、专栏前言

   本专栏开启,目的在于帮助大家更好的掌握学习Java,特别是一些Java学习者难以在网上找到系统地算法学习资料帮助自身入门算法,同时对于专栏内的内容有任何疑问都可在文章末尾添加我的微信给你进行一对一的讲解。
   但最最主要的还是需要独立思考,对于本专栏的所有内容,能够进行完全掌握,自己完完全全将代码写过一遍,对于算法入门肯定是没有问题的。
   算法的学习肯定不能缺少总结,这里我推荐大家可以到高校算法社区将学过的知识进行打卡,以此来进行巩固以及复习。
  学好算法的唯一途径那一定是题海战略,大量练习的堆积才能练就一身本领。专栏的任何题目我将会从【题目描述】【解题思路】【模板代码】【代码解析】等四板块进行讲解。

序、本章前言

  哈希函数我们在第20天查找元素时粗略提过,今天我们来提到它的另外一种使用场景。统计一个数组内每个数出现次数,很明显我们需要一个东西去存储信息,而哈希函数恰好就能帮助我们解决这个问题,而这一般也称之为计数法。以值为key,以出现的次数为value。像这种计数的场景,也是非常常见且重要的知识点。

一、【例题1】

1、题目描述

  给定一个整数 n ( 1 ≤ n ≤ 1 e 5 ) n(1 \le n \le1e5) n(1n1e5) ,然后给定 n n n个整数 a i ( 1 ≤ 1 e 5 ) a_i(1 \le 1e5) ai(11e5),统计每个数出现的次数并打印出来。

2、解题思路

  像序章所言,我们以数值为key,以出现的次数为value,利用哈希函数进行存储,由于每个数的值的范围在 [ 1 , 1 e 5 ] [1,1e5] [1,1e5],我们同样也可以使用数组模拟哈希表,下标替代数值,下标存储的值替代出现次数。

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、代码解析

  • ( 1 ) (1) (1)map.keySet函数是拿到key的映射集,帮助我们去遍历得到所有的value,这种循环样式在Java中称为增强for循环。
  • ( 2 ) (2) (2)哈希函数和数组哈希有啥区别呢?其实本质原理是相同的,不过各有优缺点,我们分别讨论一下。
  • ( 3 ) (3) (3)哈希函数,优势在于不需要去考虑存储的key的值是多少,都可以直接进行存储,但由于涉及哈希碰撞以及函数调用等原因,效率肯定是不如数组哈希的。
  • ( 4 ) (4) (4)数组哈希,优势在于数组的操作效率非常高,劣势在于如果存储的值范围非常大,那就需要开一个很大的数组,空间很浪费,做题容易MLE,这时得需要进行配合哈希来进行离散化,这就有点本末倒置了。如果值域还存在负数,还需要进行偏移,因为数组下标没有负数。

三、推荐专栏

《零基础学算法100天》

四、课后习题

序号 题目链接 难度评级
1 设计哈希集合 1
2 设计哈希映射 1
学习有疑问?

你可能感兴趣的:(《Java入门100练》,哈希算法,java,算法,数据结构,开发语言)