Hash表简介

基本思想

哈希存储的基本思想是根据当前待存储数据的特征,以记录关键字(key)为自变量,设计一个哈希函数Hash,根据Hash计算出对应的函数值Hash(key),以这个值(哈希地址)作为数据元素的地址,并将数据元素存入到相应地址的存储单元中。按照这个思想构造的表就叫做哈希表(Hash table,也叫散列表)

查找时再根据要查找的关键字key采用同样的函数计算出哈希地址,然后根据Hash(key)直接到相应的存储单元中去取要找的数据元素即可。

建立步骤

step 1:取数据元素的关键字key,计算其哈希函数值(地址)。若该地址对应的存储空间还没有被占用,则将该元素存入;否则执行step2解决冲突。

step 2:根据选择的冲突处理方法,计算关键字key的下一个存储地址。若下一个存储地址仍被占用,则继续执行step 2,直到找到能用的存储地址为止。

问题

对于n个数据元素的集合,总能找到关键字与存放地址一一对应的函数。假设最大关键字为m,可以分配m个数据元素存放单元,选取函数Hash(key)=key即可,但是这样会造成存储空间的很大浪费,甚至不可能分配这么大的存储空间。通常关键字的集合比哈希地址集合大得多(tips:这里的大不是说个数,而是总体所用空间),因而经过哈希函数变换后,可能将不同的关键字映射到同一个哈希地址上,这种现象称为冲突(Collision)。映射到同一哈希地址上的关键字称为同义词。可以说,冲突不可能避免,只能尽可能减少。

Hash表实现

通过文章前面的了解我们可以知道,具体去实现Hash表需要我们完成:1)Hash函数构造;2)制定解决冲突的方案。

Hash函数构造

构造哈希函数的方法有很多,总的原则是尽可能简单,以便提高转换速度,且要尽可能将关键字集合空间均匀的映射到地址集合空间中,同时尽可能降低冲突发生的概率。

下面是一些常用的哈希函数构造方法:

  1. 直接地址法

    					Hash(key) = a*key + b(a、b为常数)
  2. 除数留余法

    					H(key) = key % p  (p ≤ m)

    取关键字除以p的余数作为哈希地址,p最好选择一个小于或等于m(哈希地址集合的个数)的某个最大素数,也可以是不包含小于20质因子的合数。

    					哈希表长度	8	16	32	64	128	256	512
    最大素数 7 13 31 61 127 251 503
  3. 数字分析法

    设关键字集合中,每个关键字均由m位组成,每位上可能有r中不同的符号。数字分析法根据r种不同符号及在各位上的分布情况,选取某几位,组合成哈希地址。所选的位应是各种符号在该位上出现的概率大致相同。

  4. 平方取中法

    对关键字平方后,按哈希表大小,取中间的若干位作为哈希地址。

  5. 折叠法(Folding)

    比如key=135790,要求Hash(key)是2位数的散列值。那么我们将key变为13+57+90=160,然后去掉高位“1”,此时Hash(key)=60,这就是他们的哈希关系,这样做的目的就是地址与每一位的key都相关,来做到“散列地址”尽可能分散的目地。

冲突处理方法

影响哈希查找效率的一个重要因素是哈希函数本身。当两个不同的数据元素的哈希值相同时,就会发生冲突。为减少发生冲突的可能性,哈希函数应该将数据尽可能分散地映射到哈希表的每一个表项中。

解决冲突的方法有以下两种:

  1. 开放地址法

    所谓开放定址法,即由关键字得到的哈希地址一旦产生了冲突,也就是说,该地址已经存放了数据元素。我们需要寻找下一个空的哈希地址,只要哈希表足够大,空的哈希地址总能找到,并将数据元素存入。常用的找空哈希地址方法有下列三种。

    (1)线性探测法

    						Hi=(Hash(key)+di)%m(1=<i<m)

    其中,Hash(key)为哈希函数,m为哈希表长度,di为增量序列1,2…,m-1,i为探测次数。

    (2)二次探测法

    地址增量序列为:di=12,−12,22,−22,...,q2,−q2(q≤m/2)d_i = 1^2, -1^2,2^2,-2^2 ,...,q^2,-q^2 (q ≤ m/2)di​=12,−12,22,−22,...,q2,−q2(q≤m/2)

    (3)双哈希函数探测法

    				Hi =( H(key) + i * RH(key) )%m ( i = 1,2,3,..., m-1 )

    H(Key) , RH(Key) 是两个哈希函数,m为哈希表长度。

    先用第一个哈希函数对关键字计算哈希地址,一旦产生地址冲突,再用第二个函数确定移动的步长因子,最后通过步长因子序列由探测函数寻找空余的哈希地址。

    		H1 = ( a+b )%m , H2 = ( a + 2b )%m , ... , Hm-1 = ( a+(m-1)*b )%m
  2. 链地址法

    将哈希值相同的数据元素存放在一个链表中,在查找哈希表的过程中,当查找到这个链表时,必须采用线性查找方法。

leetcode两数之和python实现

题目描述

给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。

你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。

示例:

给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9,所以返回 [0, 1]

基于Hash思想的实现

class Solution:
def twoSum(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[int]
"""
Hash_dict = {}
for i in range(len(nums)):
Hash_dict[nums[i]] = i
for i in range(len(nums)):
temp = target - nums[i]
if temp in Hash_dict & i != Hash_dict[temp]:
return [i,Hash_dict[temp]]

【数据结构】Hash表简介及leetcode两数之和python实现的更多相关文章

  1. leetcode 两数之和 python

      两数之和     给定一个整数数组和一个目标值,找出数组中和为目标值的两个数. 你可以假设每个输入只对应一种答案,且同样的元素不能被重复利用. 示例: 给定 nums = [2, 7, 11, 1 ...

  2. LeetCode两数之和-Python<一>

    下一篇:LeetCode链表相加-Python<二> 题目:https://leetcode-cn.com/problems/two-sum/description/ 给定一个整数数组和一 ...

  3. LeetCode两数之和

    LeetCode 两数之和 题目描述 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那两个整数,并返回他们的数组下标. 你可以假设每种输入只会对应一个答案.但是 ...

  4. leetcode - 两数之和Ⅳ 输入BST(653)

    题目描述:给定一个二叉搜索树和一个目标结果,如果 BST 中存在两个元素且它们的和等于给定的目标结果,则返回 true. 解题思路:根据二叉搜索树的特点,对二叉搜索树进行中序遍历可以得到一个从小到达排 ...

  5. Leetcode -- 两数之和Ⅰ

    1. 两数之和 题目描述:给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那两个整数,并返回他们的数组下标. 示例:给定 nums = [2, 7, 11, 15 ...

  6. leetcode两数之和go语言

    两数之和(Go语言) 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标. 你可以假设每种输入只会对应一个答案.但是,你不能重复 ...

  7. Leetcode 两数之和 (散列表)

    给定一个整数数组和一个目标值,找出数组中和为目标值的两个数. 你可以假设每个输入只对应一种答案,且同样的元素不能被重复利用. 示例: 给定 nums = [2, 7, 11, 15], target ...

  8. leetcode 两数之和 II - 输入有序数组

    给定一个已按照升序排列 的有序数组,找到两个数使得它们相加之和等于目标数. 函数应该返回这两个下标值 index1 和 index2,其中 index1 必须小于 index2. 说明: 返回的下标值 ...

  9. leetcode NO.1 两数之和 (python实现)

    来源 https://leetcode-cn.com/problems/two-sum/description/ 题目描述 给定一个整数数组和一个目标值,找出数组中和为目标值的两个数. 你可以假设每个 ...

随机推荐

  1. solus linux 中文输入法

    默认用ibus输入框架,安装ibus-libpinyin sudo eopkg install ibus-libpinyin ibus 安装好后重启 在系统设置 -区域和语言中添加中文,(记得自己设置 ...

  2. 浅谈Spring 5的响应式编程

    这篇使用Spring 5进行响应式编程的入门文章展示了你现在可以使用的一些新的non-blocking, asynchronous.感谢优锐课老师给予的指导! 近年来,由于响应式编程能够以声明性的方式 ...

  3. 查看Python安装目录 -- 一个命令

    pip --version

  4. 京东云与AI 10 篇论文被AAAI 2020 收录,京东科技实力亮相世界舞台

    美国时间2月7-12日,AAAI 2020大会在纽约正式拉开序幕,AAAI作为全球人工智能领域的顶级学术会议,每年评审并收录来自全球最顶尖的学术论文,这些学术研究引领着技术的趋势和未来.京东云与AI在 ...

  5. 吴裕雄 Bootstrap 前端框架开发——Bootstrap 字体图标(Glyphicons):glyphicon glyphicon-plus

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name ...

  6. Java按位运算符之按位取反

    一 数据储存形式 二进制在内存中以补码的形式存在. 补码首位是符号位,0表示该数是正数,1表示该数是负数.   例如:   数值 带符号的二进制原码 (首位表示符号位) 补码 内存中的形式 (*表示无 ...

  7. POJ1703 && POJ2942 &&POJ 1182 并查集 这个做法挺巧妙

    Find them, Catch them Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 37242   Accepted: ...

  8. POJ 2785:4 Values whose Sum is 0 二分

    4 Values whose Sum is 0 Time Limit: 15000MS   Memory Limit: 228000K Total Submissions: 18221   Accep ...

  9. js ajax跨域调用

    正常使用ajax调用java.com $.ajax({ type: 'get', url: 'http://www.java.com/custinfo?id=888', dataType: 'json ...

  10. Biu一Biu--GDB

    gcc常见编译选项 ** -c **:只激活预处理.编译和汇编,也就是生成obj文件 ** -S **:只激活处理和编译,把文件编译成汇编代码 ** -o **:定制目标名称,缺省的时候编译出来的可执 ...