首页 > 其他分享 >根据数字值和探究 哈希以及unordered_map实现

根据数字值和探究 哈希以及unordered_map实现

时间:2023-11-14 14:46:01浏览次数:35  
标签:map 存储 容器 无序 链表 键值 哈希 unordered

leecode里面的第一题,是两数值和,内容如下

/**************************************************************
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
示例 1:
输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
**************************************************************/
最简单的方法就是暴力枚举,直接将所有的元素全都遍历一遍。如下
img
该方法没有增加额外的存储空间,使用的内存相较于后面的方法要少,但是时间复杂度为O(N2)

后续leecode提出了疑问说能否提高算法的效率,是时间复杂度优于O(N2)
对应的解法使用哈希算法,理论来讲也比较简单,就是用 目标值=target-当前值
将所有的数组值进行哈希存储,然后将目标值与哈希存储的值进行比较,能够找到就是对应的结果
img
该方法的内存使用相较于第一种算法是有所增加的,但是整体时间复杂度下降为O(N),其实还是以空间换时间的做法。

知识延伸:
C++ unordered_map
C++ STL 标准库中,不仅是 unordered_map 容器,所有无序容器的底层实现都采用的是哈希表存储结构。更准确地说,是用“链地址法”(又称“开链法”)解决数据存储位置发生冲突的哈希表,整个存储结构如图所示。
img

其中,Pi 表示存储的各个键值对。

可以看到,当使用无序容器存储键值对时,会先申请一整块连续的存储空间,但此空间并不用来直接存储键值对,而是存储各个链表的头指针,各键值对真正的存储位置是各个链表的节点。

注意,STL 标准库通常选用 vector 容器存储各个链表的头指针。

不仅如此,在 C++ STL 标准库中,将图 1 中的各个链表称为桶(bucket),每个桶都有自己的编号(从 0 开始)。当有新键值对存储到无序容器中时,整个存储过程分为如下几步:

将该键值对中键的值带入设计好的哈希函数,会得到一个哈希值(一个整数,用 H 表示);
将 H 和无序容器拥有桶的数量 n 做整除运算(即 H % n),该结果即表示应将此键值对存储到的桶的编号;
建立一个新节点存储此键值对,同时将该节点链接到相应编号的桶上。

另外值得一提的是,哈希表存储结构还有一个重要的属性,称为负载因子(load factor)。该属性同样适用于无序容器,用于衡量容器存储键值对的空/满程序,即负载因子越大,意味着容器越满,即各链表中挂载着越多的键值对,这无疑会降低容器查找目标键值对的效率;反之,负载因子越小,容器肯定越空,但并不一定各个链表中挂载的键值对就越少。

举个例子,如果设计的哈希函数不合理,使得各个键值对的键带入该函数得到的哈希值始终相同(所有键值对始终存储在同一链表上)。这种情况下,即便增加桶数是的负载因子减小,该容器的查找效率依旧很差。

无序容器中,负载因子的计算方法为:

负载因子 = 容器存储的总键值对 / 桶数
默认情况下,无序容器的最大负载因子为 1.0。如果操作无序容器过程中,使得最大复杂因子超过了默认值,则容器会自动增加桶数,并重新进行哈希,以此来减小负载因子的值。需要注意的是,此过程会导致容器迭代器失效,但指向单个键值对的引用或者指针仍然有效。

这也就解释了,为什么我们在操作无序容器过程中,键值对的存储顺序有时会“莫名”的发生变动。

参考:https://c.biancheng.net/view/7235.html

标签:map,存储,容器,无序,链表,键值,哈希,unordered
From: https://www.cnblogs.com/seanqianye/p/17831368.html

相关文章

  • JavaSE day06【排序查找算法,Map集合,集合的嵌套,斗地主案例】测评题
    选择题题目1(多选):下列关于TreeSet集合排序的原理正确的是()选项:​ A.排序方法如果返回的是小于0,代表的是当前元素较小,需要存放在左边​ B.排序方法如果返回的是大于0,代表的是当前元素较大,需要存放在右边​ C.排序此方法如果返回的是0,代表的是当前元......
  • Hashtable和HashMap之间的区别
    HashMap的工作原理是近年来常见的Java面试题。几乎每个Java程序员都知道HashMap,都知道哪里要用HashMap,知道Hashtable和HashMap之间的区别,那么为何这道面试题如此特殊呢?是因为这道题考察的深度很深。这题经常出现在高级或中高级面试中,甚至会要求你实现HashMap来考察你的编程能力。C......
  • 无涯教程-Dart - Map(映射)
    Map对象是一个简单的键/值对,Map中的键和值可以是任何类型,Map是动态集合,换句话说,Map可以在运行时增长和收缩。您需要将键/值对(key/value)放在大括号"{}"中,这是它的语法-varidentifier={key1:value1,key2:value2[,…..,key_n:value_n]}构造函数声明Map的语法如下-var......
  • springboot使用requestmapping创建xml响应体接口
    entity下创建类文件,类名分别为:ResponseXml,ResponseItemcontroller下创建xml响应体实现方法getResponseWithXml---------ResponseXmlStart-------importjavax.xml.bind.annotation.*;//根标签@XmlRootElement(name="test1")publicclassResponseXml{privateStringum......
  • 字符串哈希
    方法通常采用多项式Hash的方法,也就是说将字符串看做一个b进制的数。进制数选择(大于所有字符对应的数字的最大值,且为质数),如:1312331333119260817等。模数选择(双\(10^9\)的模数或者直接自然溢出):1926081719660813等。然后就可以愉快的哈希了!code(自然溢出)ullhashh(s......
  • 【8.0】Go语言基础之可变函数参数、map的使用
    【一】可变长参数【1】任意长度的指定类型的参数packagemainimport"fmt"funcmain(){ //可变长参数 //调用函数 foo(1,2,3,4,5,6) //这是接收到的参数a:>>>>[123456] //这是接收到的参数a的类型:>>>>[]int}//可以接收任意长度的int类......
  • 2023-11-11:用go语言,字符串哈希+二分的例题。 给定长为 n 的源串 s,以及长度为 m 的模式
    2023-11-11:用go语言,字符串哈希+二分的例题。给定长为n的源串s,以及长度为m的模式串p,要求查找源串中有多少子串与模式串匹配,s'与s匹配,当且仅当s'与s长度相同,且最多有k个位置字符不同。其中1<=n,m<=10^6,0<=k<=5。来自左程云。答案2023-11-11:go代码用灵捷3.5......
  • 2023-11-11:用go语言,字符串哈希+二分的例题。 给定长为 n 的源串 s,以及长度为 m 的模式
    2023-11-11:用go语言,字符串哈希+二分的例题。给定长为n的源串s,以及长度为m的模式串p,要求查找源串中有多少子串与模式串匹配,s'与s匹配,当且仅当s'与s长度相同,且最多有k个位置字符不同。其中1<=n,m<=10^6,0<=k<=5。来自左程云。答案2023-11-11:go代码用......
  • 重新学习算法_Day3-哈希表&2283&str与list转换
    HashTable 感觉从原理上说会用但是实际应用感觉不知道有什么用或者不知道怎么用例如:给你一个下标从 0 开始长度为 n 的字符串 num ,它只包含数字。如果对于 每个 0<=i<n 的下标 i ,都满足数位 i 在 num 中出现了 num[i]次,那么请你返回 true ,否则返回......
  • vue-cli-service vue.config.js配置 productionSourceMap与webpack中的devtool 关联详
    https://webpack.js.org/configuration/devtool/https://cli.vuejs.org/zh/config/#productionsourcemap https://github.com/vuejs/vue-cli/blob/f0f254e4bc81ed322eeb9f7de346e987e845068e/packages/%40vue/cli-service/lib/config/prod.js#L7 可以在源码中看到if(pro......