LeetCode---哈希表

哈希表

哈希表是根据关键码的值进行访问的数据结构,例如:python中的dict。list也可以称为hash表,可以通过下标直接访问某个元素。
在这里插入图片描述

哈希表能解决的问题

一般哈希表都是用来快速判断一个元素是否出现集合里。例如要查询一个名字是否在这所学校里。要枚举的话时间复杂度是O(n),但如果使用哈希表的话, 只需要O(1) 就可以做到。

只需要初始化把这所学校里学生的名字都存在哈希表里,在查询的时候通过索引直接就可以知道这位同学在不在这所学校里了。将学生姓名映射到哈希表上就涉及到了「hash function ,也就是哈希函数」。

哈希碰撞

如图所示,通过哈希函数计算,小李和小王都映射导了哈希表的下标为1的位置,这就导致同一个key上出现了多个value,即哈希碰撞。
在这里插入图片描述

哈希碰撞的解决办法

线性探测 Linear Probing

  1. 如下图,通过哈希函数h计算h(77)=0,故将77插入到下标为0的位置。
  2. 计算h(44)=0,但是下标为0#的位置已经被77占据,故向后找到下标为1#的空位。
  3. 计算h(55)=0,同理发现下标0#被77占据,向后找1也被44占据,继续向后找到下标为2#的位置。
  4. 计算h(20)=9,发现9#已经被31占据,向后找,再从头开始找到下标为3#的空位。
    在这里插入图片描述
    注意:如果通过h计算的位置没有找到查找项的话,就需要向后顺序查找,直到找到一个空位即查找失败。

拉链法

将原本只能容纳一个元素的槽位扩展为容纳数据项的集合,这样每个位置就能容纳多个元素,查找数据项时就需要查找同一个槽中的整个集合。
在这里插入图片描述

LeetCode

242. 有效的字母异位词

题目链接

# 时间复杂度: O(len(s+t))
# 空间复杂度: O(s_hash)
def isAnagram(s, t):
	# 遍历s,获取每个字母在s中的个数
    s_hash = {}
    for i in s:
        if i not in s_hash:
            s_hash[i] = 1
        else:
            s_hash[i] += 1

	# 遍历t,如果字母没有在s_hash中返回False;如果在则-1.
    for i in t:
        if i not in s_hash:
            return False
        else:
            s_hash[i] -= 1
            # 等于0时则删除key
            if s_hash[i] == 0:
                s_hash.pop(i)

    return s_hash == {}

第349题. 两个数组的交集

题目链接

def intersection(nums1, nums2):

    nums1_hash = {}
    result = []
    for i in nums1:
        if i not in nums1_hash:
            nums1_hash[i] = 1
        else:
            nums1_hash[i] += 1

    for i in nums2:
        if i in nums1_hash and i not in result:
            result.append(i)

    return result

350. 两个数组的交集 II

题目链接

    result = []
    hash_map1 = {}
    for num in nums1:
        if num not in hash_map1:
            hash_map1[num] = 1
        else:
            hash_map1[num] += 1

    hash_map2 = {}
    for num in nums2:
        if num not in hash_map2:
            hash_map2[num] = 1
        else:
            hash_map2[num] += 1

    for num, count in hash_map1.items():
        if hash_map2.get(num):
            if hash_map2[num] > count:
                result.extend([num] * count)
            else:
                result.extend([num] * hash_map2[num])

    return result

202. 快乐数

题目链接

def isHappy(n):

    temp_res = 0
    seen = set()

    length = len(str(n))
    while True:
    	# 每位平方相加得到temp_res
        while length > 0:
            m, n = divmod(n, 10**(length-1))
            length -= 1
            temp_res += m**2
		# 等于1 即为快乐数
        if temp_res == 1:
            return True
		# 记录出现过的数字
        if temp_res not in seen:
            n = temp_res
            length = len(str(n))
            seen.add(temp_res)
            temp_res = 0
        # 如果出现过则会导致死循环,则不是快乐数
        else:
            return False

1. 两数之和

题目链接

def twoSum(nums, target):

    # 获取每个值对应的下标hash
    nums_hash = {}
    for index, i in enumerate(nums):
        if i not in nums_hash:
            nums_hash[i] = [index]
        else:
            nums_hash[i].append(index)

    for key, val in nums_hash.items():
        # 查找差值是否存在
        sub = target-key
        if sub not in nums_hash:
            continue
        elif sub == key:
            if len(val) == 1:
                continue
            else:
                return val
        else:
            return [val[0], nums_hash[sub][0]]

更优解:

def two_sum(nums: List[int], target: int) -> List[int]:
    hash_map = {}
    for index, num in enumerate(nums):
        sub = target - num
        # 一开始hash_map是空的, 比如target = 6, nums = [2,3,4],遇到2时hash_map中没有6-4,则hash_map[2] = 0
        # 继续向后遍历总会遇到 4,再查询hash_map时,2已经保存在其中,获取其下标即可。
        # 因此不需要先整体遍历一次nums记录所有num-index映射
        if sub in hash_map:
            return [index, hash_map[sub]]
        else:
            hash_map[num] = index

454. 四数相加 II

题目链接

# 时间复杂度:O(n^2)
# 空间复杂度: O(n)
def fourSumCount(A, B, C, D):

    ans = 0
    # 直接暴力计算的话时间复杂度要O(n^4),肯定会超时
    # 这里采用分治,将4个列表分为两组,先计算AB两组两两元素和,及出现次数
    AB_hash = {}
    for index_a, a in enumerate(A):
        for index_b, b in enumerate(B):
            if (a + b) not in AB_hash:
                AB_hash[a+b] = 1
            else:
                AB_hash[a+b] += 1

    # 计算 0-c-d 是否在AB_hash中,如果在就存在解
    for c in C:
        for d in D:
            if (-c-d) in AB_hash:
                ans += AB_hash[-c-d]

    return ans
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值