一个题目
该题目来自58同城的二面,用最快速度求两个数组之交集算法。
比如A={6,2,4,1},B={2,9,4,3},那么A&B={2,4}。
算法一:在大多数情况,也就是一般的情况下,大家都能想出最暴力的解法,通常也就是采用遍历或者枚举的办法来解决问题。
该题需要找出两个数组的交集,最简单的一个办法就是用A数组里面的所有数去匹配B数组里面的数。假设两个数组的大小都是n,那么这种遍历的时间复杂度为O(n^2)。这个也是最复杂的情况了。
算法二:通常下,除了用暴力枚举的问题,还有另外一种外万金油的解法----预处理。其实思想和C语言中的预处理一样,对数据记性归一化处理。说白了,在这里就是对数组排序。我们知道数组排序的算法时间复杂度最低是O(nlogn),可以看到数量级已经低于算法一的时间复杂度。
那么在排好序好,怎么得到数组的交集呢?
假设我们已经有了两个排好序的数组:
A={1,2,4,6}
B={2,3,4,9}
那么我们只要分别对A和B设置两个指针i,j(或者直接说是下标),进行循环,伪代码如下:
int count()
{
total=i=j=0;
while(i<n && j<n)
{
if(a[i]<b[j]) i++;
else if(a[i]>b[j])j++
else
total++;
}
return total;
}
时间复杂度为O(n)
综合排序的时间复杂度则整体复杂度为:O(nlogn)
算法三:如果只是会了上面两种,还只能说是计算机的菜鸟,而且一般面试或者笔试题也不会这么简单。那么比O(nlogn)时间复杂度更低的是多少呢?一般就是O(n)。我们可以思考一下计数排序的算法。也就是把两个数组A和B都遍历到一个新的数组里,然后在统计重复的数字即可,这个时间复杂度就是O(n)。当然,计数排序是有条件的,也就是要求数组内数字的范围是已知并且不是很大。
算法四:上面的算法实现简单,也很容易达到题目的要求,但是还是有一些瑕疵,也就是非完美方案,同样根据算法三我们可以想出用哈希函数或者哈希表来解决问题。也就是将数组A哈希到哈希表中,然后继续将数组B哈希到哈希表中,如果发生哈希碰撞则统计加1,最后可以得出数组的交集。时间复杂度也就是哈希所有元素的复杂度O(n)。
那么什么是哈希呢?

Hash ,一般翻译做“ 散列” ,也有直接音译为“ 哈希” 的,就是把任意长度的输入(又叫做预映射, pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不 同的输入可能会散列成相同的输出,而不可能从散列值来唯一的确定输入值。简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。

HASH 主要用于信息安全领域中加密算法,它把一些不同长度的信息转化成杂乱的128 位的编码, 这些编码值叫做HASH 值. 也可以说,hash 就是找到一种数据内容和数据存放地址之间的映射关系

例如字符串 hello 的哈希算法

char* value = "hello"; int key = (((((((27* (int)'h'+27)* (int)'e') + 27)  * (int)'l') + 27) * (int)'l' +27) * 27 ) + (int)'o' ; 。

数组的特点是:寻址容易,插入和删除困难;而链表的特点是:寻址困难,插入和删除容易。那么我们能不能综合两者的特性,做出一种寻址容易,插入删除也容易 的数据结构?答案是肯定的,这就是我们要提起的哈希表,哈希表有多种不同的实现方法,我接下来解释的是最常用的一种方法—— 拉链法,我们可以理解为“ 链表 的数组” ,如图:

HashMap其实也是一个线性的数组实现的,所以可以理解为其存储数据的容器就是一个线性数组。这可能让我们很不解,一个线性的数组怎么实现按键值对来存取数据呢?这里HashMap有做一些处理。

 

1.首先HashMap里面实现一个静态内部类Entry 其重要的属性有 key , value, next,从属性key,value我们就能很明显的看出来Entry就是HashMap键值对实现的一个基础bean,我们上面说到HashMap的基 础就是一个线性数组,这个数组就是Entry[],Map里面的内容都保存在Entry[]里面。

2.既然是线性数组,为什么能随机存取?这里HashMap用了一个小算法,大致是这样实现:

Java代码  
  1. 存储时:
  2. int hash = key.hashCode();--> 这个hashCode方法这里不详述,只要理解每个key的hash是一个固定的int值
  3. int index = hash % Entry[].length;
  4. Entry[index] = value;
  5. 取值时:
  6. int hash = key.hashCode();
  7. int index = hash % Entry[].length;
  8. return Entry[index]

到这里我们轻松的理解了HashMap通过键值对实现存取的基本原理

3.疑问:如果两个key通过hash % Entry[].length得到的index相同,会不会有覆盖的危险?

这里HashMap里面用到链式数据结构的一个概念.上面我们提到过Entry类里面有一个next属性,作用是指向下一个Entry。打个比方, 第一个键值对A进来,通过计算其key的hash得到的index=0,记做:Entry[0] = A.一会后又进来一个键值对B,通过计算其index也等于0,现在怎么办?HashMap会这样做:B.next = A,Entry[0] = B,如果又进来C,index也等于0,那么C.next = B,Entry[0] = C;这样我们发现index=0的地方其实存取了A,B,C三个键值对,他们通过next这个属性链接在一起。所以疑问不用担心。

到这里为止,HashMap的大致实现,我们应该已经清楚了。

当然HashMap里面也包含一些优化方面的实现,这里也啰嗦一下。

比如:Entry[]的长度一定后,随着map里面数据的越来越长,这样同一个index的链就会很长,会不会影响性能?

HashMap里面设置一个因素(也称为因子),随着map的size越来越大,Entry[]会以一定的规则加长长度。

解决hash冲突的办法

1)开放定址法(线性探测再散列,二次探测再散列,伪随机探测再散列)

2)再哈希法

3)链地址法

4)建立一 公共溢出区

java 中hashmap的解决办法就是采用的链地址法。

最快速度求两个数组之交集算法与hash相关推荐

  1. 最快速度求两个数组之交集算法

    该题目来自58同城的二面,用最快速度求两个数组之交集算法. 比如A={6,2,4,1},B={2,9,4,3},那么A&B={2,4}. 算法一:在大多数情况,也就是一般的情况下,大家都能想出 ...

  2. Java求两个数组的交集、差集、并集

    目录 Java求两个数组的并集,代码如下: Java求两个数组的交集,代码如下: Java求两个数组的差集,代码如下: 交集.差集.并集测试代码如下: Java求两个数组的并集,代码如下: /*** ...

  3. php 两个数组求交集_如何求两个数组的交集

    题目描述 给定两个数组,编写一个函数来计算它们的交集. 示例 1: 输入:nums1 = [1,2,2,1], nums2 = [2,2]输出:[2] 示例 2: 输入:nums1 = [4,9,5] ...

  4. 求两个数组的交集和并集

    晚上闲来无事,想起前两天查资料时候,看到别人一篇博客标题关于数组的交集和并集,晚上也随便写写,权当督促自己坚持经常练习练习写写小Demo.如下,先来一段求有序数组的交集的代码,代码如下: public ...

  5. js寻找两个数组的差集_js求两个数组的交集|并集|差集|去重

    let a = [1,2,3], b= [2, 4, 5]; 1.差集 (a-b 差集:属于a但不属于b的集合)  a-b = [1,3] (b-a 差集:属于b但不属于a的集合)  b-a = [4 ...

  6. PHP求两个数据的交集,php计算两数组交集两个函数_PHP教程

    ,使用 array_intersect 求两个数组的交集比使用 array_diff 求同样两个数组的并集要快. 如果要求数组 $a 与数组 $b 的差集的个数,应该使用 count($a) - co ...

  7. 使用Set求两个数组的并集|| 交集||差集

    这里要讲解一下,使用Set求两个数组的并集|| 交集||差集. 先定义两个数组: let a = new Set([1, 2, 3]);let b = new Set([4, 3, 2]); 并集 l ...

  8. PHP实现求两个数组的并集

    $thiscates = explode(",", $iddata['cates']) ; $getcates = $_GPC['cates']; $allcates = arra ...

  9. 算法训练Day6 | LeetCode:242. 有效的字母异位词(数组作哈希表);349. 两个数组的交集(Set作哈希表);202.快乐数 (Set作哈希表);1. 两数之和(Map作哈希表)

    目录 LeetCode242. 有效的字母异位词 方法:数组作哈希表 1. 思路 2. 代码实现 3. 复杂度分析 4. 思考 Leetcode349. 两个数组的交集 方法一:用Set作HashMa ...

最新文章

  1. 网站真分页js代码该怎么写? 1
  2. Python批量剪裁图片
  3. STM32开发 -- Keil使用(2)
  4. SAP Fiori Launchpad launchpad Designer组件和configuration组件的重要存储表一览
  5. visual studio 2017 显示行号
  6. Java加密与解密的艺术~数字签名~RSA实现
  7. 图像局部特征(六)--斑点检测之SIFT算法原理总结补充
  8. 剑指Offer——二维数组中的查找
  9. python中基础知识_Python中的一些基础知识
  10. netty 异常 did not read anything but decoded a message
  11. 表单验证:名称、电话号码、邮箱
  12. draft伦理——第七章
  13. 编译原理复习(5)语法分析--自下而上分析
  14. 球球大作战服务器维护时间,2018球球大作战每日解除限制时间是几点 | 手游网游页游攻略大全...
  15. ConvLSTM-AE for VAD (ICME2017-SIST)
  16. win10系统怎么qq远程连接到服务器,QQ远程控制功能在Win10系统上无法使用怎么解决...
  17. Halcon12 HObject与VC++ OpenCV Mat相互转换
  18. python学习教程26-转换Series的数据类型
  19. 计算机联到同一个局域网,两台电脑连接同一个wifi算是局域网么
  20. 软件产品与项目开发的区别

热门文章

  1. 2023秋招大厂经典面试题及答案整理归纳(1-20)校招必看
  2. 打造有企业特色的ERP
  3. 解决0X80042412错误,恢复已备份的Widows 8.1系统镜像到另一个固态硬盘。
  4. ApiCloud使用小结图文示例-简单的认识
  5. 移动端开发(学好移动端这一篇就够啦)
  6. R语言入门基础——基础操作篇(极为基础的指令代码)
  7. 稳定kvm服务器vps,kvm的服务器vps
  8. 如何写好一份产品需求文档
  9. 最优化方法与实践-抛物线法(matlab)
  10. MySQL图形化用户界面客户端的安装与介绍(SQLyog)