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. git杂碎汇总

    1. .gitignore文件使用 1.如果不想某类文件(编译后.配置等文件)加入到git版本管理,可以在这个文件中配置规则,进行过滤筛选: 2.配置规则 以斜杠"/"表示目录:e ...

  2. 01.Delphi最简单的接口

    我想学习一个插件框架,但是那个框架里面大量用到了接口,于是不得不把接口看一下了.总感觉接口编程这一块非常的绕,每一行都注释了. unit Unit1; interface uses Windows, ...

  3. numpy.linspace使用详解

    numpy.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None) 在指定的间隔内返回均匀间隔的数字. 返回nu ...

  4. 看完本文,Essay写作再也不需要凑字数

    很多同学都说过自己写论文的时候出现“词穷”的情况,无奈只能靠“胡编乱造”来凑字数写出开头段,这其实是大家的阅读量没有达到要求.但不能因为出现这种情况就对自己的论文不负责任,否则你的论文分数可能就不会对 ...

  5. C# 控制台应用程序从外部传参运行和调试

    参考:/*十有三博客*/ 新建一个用于演示的控制台应用程序项目,然后在Program.cs的入口Main方法里编写如下代码 foreach (var arg in args) { Console.Wr ...

  6. 打开exe并传参

    shellexecute(Application.Handle,'open',PWideChar('E:\控件\TMS.Scripter.Studio.Pro..6.0.2.0.Delphi.BCB. ...

  7. NO3 cat-xargs-cp-mv-rm-find命令

    ·cat            #查看文件内容        eg:cat oldboy.txt·xargs        #从标准输入获取内容创建和执行命令 -n 加数字:分组 ·cp       ...

  8. P1040 有几个PAT

    转跳点:

  9. 3 —— node —— 文件追加内容

    思想 : 先读取 , 再追加 const fs = require('fs') fs.readFile("./hello.txt","utf-8",(err,d ...

  10. return , return true , return false的区别

    return true:  返回正确的处理结果. return false :  返回错误的处理结果 和 中断代码继续向下 执行. return:    返回null,起到中断方法执行的效果,只要不r ...