博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
从两个数组中查找相同的数字谈Hashtable
阅读量:6036 次
发布时间:2019-06-20

本文共 2084 字,大约阅读时间需要 6 分钟。

假设数组A有n个元素,数组B有n个元素。

看到这种题的时候,我们最直观的就是通过两层for循环来对比每个数组中的数字。因此A数组中的每个元素都会和B数组中的每个元素对比过一次,所以总共要对比的次数是n个n相加(或者是n个m相加),也就是n2(或者为n x m).

因此我们想能不能有更快的方法呢?让其中一个数组的查找的时间复杂度不再是O(n)就可以了。也就是我们在这个数组中查找一个数,不是通过遍历的方式。

但是不是通过遍历的方式能在一个数组中找到一个自己想要的数吗?看起来必须有什么特殊的方法才行。

我们再回过头来看数组是什么组成的:

1.下标

2.下标所代表的元素

 

我们按位置查找时,数组的速度是O(1)的,因为我们只需要通过下标就可以定位那个元素。否则需要采用遍历的O(n)的方式。

O(n)看起来好像速度还可以,其实想想看还真没有比它更慢的了,你都把遍历完一遍了当然知道有没有所需要的元素了。

这时,我们就想到,如果用下标位置来标示所需的数字呢,而元素用来标记是否出现,出现1次就加1。比如说数组A中存在元素12,就在由数组B转换后的数组C中检查C[12]是否等于1.

我们把数组B转换成数组C,所需要的时间也为O(n)

那就使得对A数组的遍历仍为O(n),但检查数组A中的元素是否存在于数组C中则由原来的O(n)转换为O(1).

所以总的时间复杂度为O(n+n)。

 

看起来不错,但是问题来了,如果A中的数字很大并且很分散时,会造成数组C中大量的空间被浪费。比如说数组A是由{1,333,666}这三个元素,那么辅助数组C就需要667的大小,但是只用到了其中的3个,也就是664个空间是白浪费的。

这种直接通过数组下标寻址的方法,在数组元素非连续的情况下,会造成大量空间浪费。

 

 

那什么情况下数组中的数字会比较连续呢?还记得这张图吧,:

也就是ASCII码。

所以这种方式除了用来查找数字,也可以用来查找字母

代码如下:(赶时髦用C来写,写的过程中感觉各种不适应啊。注:"abc"是作为指针传递,'abc'是作为整数传递,数组在作为参数时会退化为指针。)

#include 
#include
char * FindSameChar(char *stringA, char *stringB){
if(stringA == NULL || stringB == NULL ){
return '\0'; } const int containerSize = 128; unsigned int container[containerSize]; for (unsigned int i=0; i
= 1){
*findResult = *key; findResult++; } key++; } if (result != NULL) return result; else return '\0'; }

空间复杂度为O(1),因为这里我开的辅助内存大小为128是个常数。

 

这种下标和数字紧耦合的方式使得我们这种方法受到了极大的限制,那么我们有没有办法“解耦”呢?

也就是说,让1,和666不要离开这么远,中间空了665个空位。让他们尽可能的靠近些。这时候就需要通过一种方法来实现这种解耦,也就是说通过某个函数算出相应的位置,使得1和666之间的空格数尽量更小。

这就是hash函数。

 hash技术很好的解决了直接寻址遇到的问题,但是这么做同时也引入了新的问题,通过hash函数算出来的位置可能会相同,一般就称为发生了“碰撞"。也就是虽然我们希望通过hash函数使得1和666的位置尽量能靠近些,但是可能某些hash函数算出来的结果就是1和666位置相同。一般发生这种情况有几种方式解决,二次hash和链接法。链接法用的是最多的,就是在同一个位置上创建一个链表。

当然如果碰撞多了,hash表也变成了链结构,会极大的影响效率。当初某个BUG就是因为采用了某种hash算法导致产生大量的碰撞,使得服务器性能下降。

 

hash表用的地方非常多,比如数据库中就是用了哈希表,通常采用的是除法hash方式。

在用来设计哈希函数的除法散列法中,通过取k除以m的余数,来将关键字K映射到m个位置中的某个位置,也就是:

  hash(k) = k mod m;

顺便值得一提的是,获取余数是个经常用到的方法,比如说两人跑步套圈,迷宫中的右手扶墙算法等。也就是说能让一个数不停的在一个指定的范围内打转。

.NET中相应的实现是HashSet<T>,Dictionary<TKey,TValue>,Hashtable。

当然这几种结构肯定有区别,下次再说吧。

 

(ps:话说从上个星期四来上海后面试了几家公司,但没发现什么让人high的地方)

转载地址:http://feohx.baihongyu.com/

你可能感兴趣的文章
个人关于vue全家桶开发规范的梳理
查看>>
【论文实现】一篇Sigkdd的弹幕分析论文的python实现【LDA 实践者】
查看>>
十几行代码教你实现一个最简版的promise
查看>>
Java IO学习笔记八
查看>>
systemd vs supervisord
查看>>
如何构建一个分布式爬虫:基础篇
查看>>
50 行代码的 HTML 编译器
查看>>
[GitHub] vim 实操教程
查看>>
常见网络攻击--XSS && CSRF
查看>>
在项目中使用echarts
查看>>
Akka系列(四):Akka中的共享内存模型
查看>>
腾讯云语音合成TTS
查看>>
[LeetCode] Find Largest Value in Each Tree Row
查看>>
【Sublime Text】安装插件
查看>>
javascript正则表达式
查看>>
快速初始化express项目
查看>>
EGO走进美团——追寻千亿市场背后的技术力量
查看>>
将敏捷应用于工业机械开发
查看>>
中台之上(六):如何为一个商业银行设计业务架构?
查看>>
开源项目koa-router被叫卖,周下载10W+只要5000美元
查看>>