笔者在读研刚开始的时候,偶尔看面经,有这样一个问题:只用2GB内存在20亿个整数中找到出现次数最多的数,当时的我一脸懵逼,怎么去思考,20亿个数?What The Fuck! 但是,看完今天的文章,你或许就会觉得原来也不过如此啊!其核心就是哈希函数和哈希表的应用!

哈希函数

哈希函数又称为散列函数,就是把任意长度的输入(又叫做预映射, pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,而不可能从散列值来唯一的确定输入值。假设输出值域为S,哈希函数的性质如下:

  1. 典型的哈希函数都有无限的输入值域
  2. 当哈希函数输入一致时,输出必相同
  3. 当哈希函数传入不同的输入值时,返回值可能一样,也可能不一样,由于输入域远大于值域
  4. (重要)很多的不同输入所得的输出值会均匀的分布在S上(但不是绝对均匀)

最后一个性质对于一个优秀的哈希函数是非常重要的,并且这种均匀与数据的输入规律无关。比如“aa1”、"aa2"经过hash后可能结果会相差很多,当一个哈希函数的输出在S中是均匀的,那么我们将输出值对m取余(%m),就会将不定长输入映射到0~m-1空间中,并且在这个空间也保持均匀分布!哈希表就是这么做的,一会再说!哈希函数还有以下特点:

  1. 免碰撞:即不会出现输入 x≠y ,但是H(x)=H(y) 的情况,其实这个特点在理论上并不成立,比如目前比特币使用的 SHA256 算法,会有

    种输出,如果我们进行
    + 1 次输入,那么必然会产生一次碰撞,事实上,通过 理论证明 ,通过
    次输入就会有99%的可能性发生一次碰撞,不过即使如此,即便是人类制造的所有计算机自宇宙诞生开始一直运算到今天,发生一次碰撞的几率也是极其微小的。
  2. 隐匿性:也就是说,对于一个给定的输出结果 H(x) ,想要逆推出输入 x ,在计算上是不可能的。如果想要得到 H(x) 的可能的原输入,不存在比穷举更好的方法。

常见的哈希函数有:SHA1、MD5、SHA2等

哈希表

哈希表就是利用哈希函数,可以根据关键码而直接进行访问的数据结构,也就是将关键码(Key value)通过哈希函数映射到表中的一个位置来进行访问。由于是直接访问,所以对于哈希表的元素理论上的增删改查时间复杂度都是O(1)。

而计算散列地址的方法有很多种,通常我们使用的是除留余数法,也就是说使用哈希函数对关键字得到的输出值对散列表长度取余得到的余数即为散列地址。

哈希冲突

由于我们的输入长度和范围是任意的,但是经过哈希函数后的输出值域是固定的,所以必然会产生冲突。如上图的buckets152(红色区域)就相当于发生冲突!处理冲突的方法有:

  • 开放地址法
  • 再散列法
  • 公共溢出法
  • 拉链法(经典、重点)
    我们来说下拉链法,也如上图所示,拉链法的思路很简单,就是当发生哈希冲突后,会在当前地址区域建立一个链表,将冲突目标添加到链表中去。这种方式也不太好,当冲突发生过多时,链表的查找方式效率也就不是很高了!
    因此对于JAVA中(C++标准中没有hashmap,只有第三方的),hashmap的实现也是类似,但是有一点改进,也就是如果发生冲突,将冲突对象添加到链表,假设冲突个数达到了8次,那么就会使用红黑树来代替链表,以加快查找速度。冲突个数少时,没有必要使用红黑树

C++中的hash_map

c++的hash_map和map的用法很类似,但一定要区别,map和hash_map虽然都是key-value形式,但是map的底层是红黑树,而hash_map的底层是hash表!如果在Linux下使用hash_map,一定要加上一个__gnu_cxx的命名空间声明!

#include

题目:2G内存下在20亿数据中找到出现次数最多的数

首先我们确定value的范围,如果一个数出现了20亿次,那么value就为20亿次。因此我们使用32位的正整型,也就是4B的空间,同理key也是4B的空间,因此一条记录(Entry)需要8B的空间,当记录为20亿个时,需要至少16GB的内存。
在极端最差的状态,20亿个数都不相同,那么哈希表中可能会有20亿条记录,这样的话显然内存不足,因此一次性统计20个数风险很大。解决方案:将包含有20亿个数的大文件分成16个小文件,利用哈希函数,这样的话,同一个重复的数肯定不会分到不同的文件中去,并且,如果哈希函数足够好,那么这16个文件中不同的数也不会大于2亿(20 / 16)。然后我们在这16个文件中依次统计就可以了,最后进行汇总得到重复数最多的数。当然如果使用分布式系统,那么可以利用哈希函数将这些数据分配到不同的电脑上去!
如果想要看更多精彩内容,请关注我的个人公众号 (算法工程师之路)希望大家多多支持哦~

公众号简介:分享算法工程师必备技能,谈谈那些有深度有意思的算法,主要范围:C++数据结构与算法/深度学习(CV),立志成为Offer收割机!坚持分享算法题目和解题思路(Day By Day)

算法工程师之路

igs无法分配驱动器映射表_左神算法基础:哈希函数和哈希表相关推荐

  1. java取余数的函数_左神算法基础:哈希函数和哈希表

    笔者在读研刚开始的时候,偶尔看面经,有这样一个问题:只用2GB内存在20亿个整数中找到出现次数最多的数,当时的我一脸懵逼,怎么去思考,20亿个数?What The Fuck! 但是,看完今天的文章,你 ...

  2. igs无法分配驱动器映射表_利用VBA获取驱动器的信息

    大家好,我们今日讲解"VBA信息获取与处理"教程中第十七个专题"文件及文件夹信息的获取及操作"的第三节"利用VBA获取文件的信息和属性",这 ...

  3. igs无法分配驱动器映射表_项目超过255个摄像机怎么分配IP地址

    ------ 欢迎新老朋友们加入微信群,方便技术讨论,信息互通,行业交流:智能弱电行业专家群:智能弱电行业技术群:智能弱电行业信息群:申请加入请加小编微信:15537112161------- 我们做 ...

  4. igs无法分配驱动器映射表_硬盘无法使用,用DiskPart进行分区和格式化,非常简单...

    如果计算机硬盘出现问题,有时不是硬件上出现了错误,很可能只是逻辑上出现了问题,这时就可以使用DiskPart来快速解决. 在Windows 10上,当外部存储(例如U盘.可移动硬盘或SD卡)由于数据损 ...

  5. igs无法分配驱动器映射表_如何同步本地文件到网络驱动器/NAS?

    ​在我们的生活中,有多种原因促使我们需要将文件夹同步到(网络驱动器)共享文件夹或NAS.例如,想要脱机查看先前可用的文件夹.同步文件夹的作用:自动保存两个或多个相同的文件夹,并将所有更改的文件夹从源目 ...

  6. igs无法分配驱动器映射表_关于光盘读取二三事(解决UDF多次刻录无法读取问题)...

    点击关注上方"消遣杂谈",关注后了解更多内容. 目的:修改注册表的相关信息,实现光盘自由的读取,减少资源的浪费. 前言:在平时工作中,经常遇到别的电脑刻录的光盘放到另外一台电脑中无 ...

  7. 左神算法基础班4_4_3在二叉树中找到一个节点的后继节点

    Problem: 在二叉树中找到一个节点的后继节点 [题目] 现在有一种新的二叉树节点类型如下: public class Node { public int value; public Node l ...

  8. 左神算法基础班3_13深度拷贝含有随机指针的链表

    Problem: 复制含有随机指针节点的链表 [题目] 一种特殊的链表节点类描述如下: public class Node { public int value; public Node next; ...

  9. 0206.BFPRT在一大堆数中求其前k大或前k小的问题,简称TOP-K问题(左神算法基础班源码)

    package basic_class_02;/*** * 在一大堆数中求其前k大或前k小的问题,简称TOP-K问题.* 而目前解决TOP-K问题最有效的算法即是BFPRT算法**/ public c ...

最新文章

  1. android脚步---设置layout隐藏属性
  2. 两个pytorch版本Fnet
  3. java oom分析_作为测试你应该知道的JAVA OOM及定位分析
  4. 云起实验室有奖征文,精美好礼等你来领——《我的linux初体验》
  5. 平板安装python_在CentOS上安装Python3的三种方法
  6. 图像分类_01图像分类简介:挑战+近邻分类器+CIFAR-10数据集概述
  7. 使用组策略禁止域用户运行特定软件名称的程序
  8. php 操作系统,PHP 处理文件和操作系统
  9. C#的yield return是怎么被调用到的?
  10. 收藏一篇关于 用两个栈实现一个队列功能的帖子
  11. WPF-21:WPF实现仿安卓的图案密码键盘(改进)
  12. 强化狼群等级制度的灰狼优化算法-附代码
  13. python画3维图_python如何画三维图像?
  14. win10服务和控制器应用CPU占用过高
  15. mysql带条件的插入语句
  16. Altium Designer 18中的Multi-board Schematic–Defaults
  17. 光量子计算机的功能,光量子计算机有什么用
  18. 常州SEO姜东:技术搜索引擎优化
  19. ME02 认知之2017罗胖跨年演讲
  20. Google、迅雷与李开复、周鸿祎的那点破事

热门文章

  1. perl,shell中如何打印出处理sql语句变量的单引号
  2. ROS机器人程序设计(原书第2版)3.9 3D可视化
  3. 关于CSS一些细节问题
  4. 内核态文件操作【转】
  5. 个推如何管理亿级代码的质量?持续集成SonarQube 代码质量管理系统
  6. 集成CCFlow工作流与GPM的办公系统驰骋CCOA介绍(二)
  7. Linux常用的基本命令13
  8. 如何学习一个新的系统
  9. HTML5的革新:结构之美
  10. halcon学习之阈值分割(threshold、binary_threshold、dyn_threshold、var_threshold、auto_threshold、fast_threshold、)