算法理论——哈希表(附多例题)

简介: 哈希表也叫散列表,哈希表是一种数据结构,它提供了快速的插入操作和查找操作,无论哈希表总中有多少条数据,插入和查找的时间复杂度都是为O(1),因为哈希表的查找速度非常快,所以在很多程序中都有使用哈希表,例如拼音检查器。

一、什么是哈希表

哈希表也叫散列表,哈希表是一种数据结构,它提供了快速的插入操作和查找操作,无论哈希表总中有多少条数据,插入和查找的时间复杂度都是为O(1),因为哈希表的查找速度非常快,所以在很多程序中都有使用哈希表,例如拼音检查器。

哈希表也有自己的缺点,哈希表是基于数组的,我们知道数组创建后扩容成本比较高,所以当哈希表被填满时,性能下降的比较严重。

哈希表采用的是一种转换思想,其中一个中要的概念是如何将「键」或者「关键字」转换成数组下标?在哈希表中,这个过程有哈希函数来完成,但是并不是每个「键」或者「关键字」都需要通过哈希函数来将其转换成数组下标,有些「键」或者「关键字」可以直接作为数组的下标。我们先来通过一个例子来理解这句话。

我们上学的时候,大家都会有一个学号「1-n号」中的一个号码,如果我们用哈希表来存放班级里面学生信息的话,我们利用学号作为「键」或者「关键字」,这个「键」或者「关键字」就可以直接作为数据的下标,不需要通过哈希函数进行转化。如果我们需要安装学生姓名作为「键」或者「关键字」,这时候我们就需要哈希函数来帮我们转换成数组的下标。

总之,哈希表是一个便于记录和高效查询的数据结构,插入和查找的时间复杂度都是为O(1), 使用时可以粗略的认为哈希表记录的键是问题的条件,值是问题的解,通过不断插入和搜索最终获得所需答案。

二、哈希表解题实例

1. 两数之和

题目描述

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

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。

你可以按任意顺序返回答案。

示例

输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。

思路

暴力思路是最容易想到的方法是枚举数组中的每一个数 x,寻找数组中是否存在 target - x。

当我们使用遍历整个数组的方式寻找 target - x 时,需要注意到每一个位于 x 之前的元素都已经和 x 匹配过,因此不需要再进行匹配。而每一个元素不能被使用两次,所以我们只需要在 x 后面的元素中寻找 target - x。

但是这种思路时间复杂度太高,我们使用哈希表法解决本题:

注意到暴力方法的时间复杂度较高的原因是寻找 target - x 的时间复杂度过高。因此,我们需要一种更优秀的方法,能够快速寻找数组中是否存在目标元素。如果存在,我们需要找出它的索引。

使用哈希表,可以将寻找 target - x 的时间复杂度降低到从 O(N)降低到 O(1)。

这样我们创建一个哈希表,对于每一个 x,我们首先查询哈希表中是否存在 target - x,然后将 x 插入到哈希表中,即可保证不会让 x 和自己匹配。

代码

# 两数之和
def twoSum(nums, target):
    h = dict()
    for i in range(len(nums)):
        if target - nums[i] in h:
            return [i, h[target - nums[i]]]
        else:
            h[nums[i]] = i

2. 整数转罗马字母

题目描述:

罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。

字符 数值

I 1

V 5

X 10

L 50

C 100

D 500

M 1000

例如, 罗马数字 2 写做 II ,即为两个并列的 1。12 写做 XII ,即为 X + II 。 27 写做 XXVII, 即为 XX + V + II 。

通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况:

I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。

X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。

C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。

给你一个整数,将其转为罗马数字。

思路

首先建立题目中已经给定的数值与罗马字符对应的哈希表,然后再此表中根据规律找到解。

我们用来确定罗马数字的规则是:对于罗马数字从左到右的每一位,选择尽可能大的符号值。对于 140,最大可以选择的符号值为 C=100。接下来,对于剩余的数字 40,最大可以选择的符号值为 XL=40。因此,140 的对应的罗马数字为C+XL=CXL。

代码

def intToRoman(num):
    # 构建相应哈希表
    h = dict()
    h[1] = 'I'
    h[5] = 'V'
    h[10] = 'X'
    h[50] = 'L'
    h[100] = 'C'
    h[1000] = 'M'
    h[500] = 'D'
    h[4] = 'IV'
    h[9] = 'IX'
    h[40] = 'XL'
    h[90] = 'XC'
    h[400] = 'CD'
    h[900] = 'CM'
    if num in h.keys():
        return h[num]
    # 答案
    res = ''
    # 模拟,在哈希表中找到最大值,num减去最大值,结果res加上哈希表中最大值对应的字符
    while num != 0:
        for i in sorted(h, reverse=True):
            if num >= i:
                num -= i
                res += h[i]
                break
    return res

3.二倍数对数组

题目描述

给定一个长度为偶数的整数数组 arr,只有对 arr 进行重组后可以满足 “对于每个 0 <= i < len(arr) / 2,都有 arr[2 * i + 1] = 2 * arr[2 * i]” 时,返回 true;否则,返回 false。

示例

输入:arr = [3,1,3,6]
输出:false
输入:arr = [4,-2,2,-4]
输出:true
解释:可以用 [-2,-4] 和 [2,4] 这两组组成 [-2,-4,2,4] 或是 [2,4,-2,-4]

思路

哈希表中按小到大排列记录出现个数,遍历哈希表,每个数都和它的两倍的个数或者它的一半的个数相等,当前个数小于0说明不够用,不能组合,如果不存在当前数的两倍或一半也不能组合,否则当前数的两倍或一半的数减去当前数的个数。

代码

# 二倍数对数组 哈希表的应用
def canReorderDoubled(arr):
    ant = Counter(arr)
    if ant[0] % 2 != 0:
        return False
    for i in sorted(ant, key=abs):
        if ant[2 * i] < ant[i]:
            return False
        else:
            ant[2 * i] -= ant[i]
            print(ant)
    return True
目录
相关文章
|
7月前
|
算法
带你读《图解算法小抄》六、哈希表(2)
带你读《图解算法小抄》六、哈希表(2)
|
4月前
|
存储 算法 Java
【算法系列篇】哈希表
【算法系列篇】哈希表
|
4天前
|
存储 算法 安全
数据结构与算法 哈希表
数据结构与算法 哈希表
7 0
|
1月前
|
存储 算法 Java
算法系列--哈希表
算法系列--哈希表
15 0
|
4月前
|
存储 算法 Java
数据结构与算法面试题:实现一个哈希表,并考虑哈希冲突的解决方案。
数据结构与算法面试题:实现一个哈希表,并考虑哈希冲突的解决方案。
23 0
|
5月前
|
算法 C++
【牛客-算法】NC61 两数之和(哈希表的运用,C++)
前言 🔥 该专栏作为算法题笔记,记录算法的思路、遇到的问题,以及能跑的代码,持续更新中! 🔥 推荐一款面试、刷题神器牛客网:👉开始刷题学习👈
106 1
|
7月前
|
算法 索引
带你读《图解算法小抄》六、哈希表(1)
带你读《图解算法小抄》六、哈希表(1)
带你读《图解算法小抄》六、哈希表(1)
|
10月前
|
存储 缓存 算法
趣味算法——探索哈希表的神秘世界
前言: 在编程世界中,数据存储和检索的效率常常是我们关注的重点。对于这个问题,哈希表提供了一个既高效又实用的解决方案。哈希表是一种通过哈希函数将键转化为数组索引,以实现快速查找的数据结构。在大多数情况下,哈希表能够在常数时间内完成查找,插入和删除操作,因此在许多应用场景中得到了广泛使用。
48 0
|
11月前
|
算法 数据安全/隐私保护 索引
【数据结构与算法】哈希表2:四数相加II & 赎金信 & 三数之和 & 四数之和
【数据结构与算法】哈希表2:四数相加II & 赎金信 & 三数之和 & 四数之和
43 0
|
11月前
|
存储 算法 C++
【数据结构与算法】哈希表1:字母异位词 & 两数交集 & 快乐数 & 两数之和
【数据结构与算法】哈希表1:字母异位词 & 两数交集 & 快乐数 & 两数之和
48 0