《代码随想录》Day6: 哈希表Into + 242.有效的字母异位词 + 349. 两个数组的交集 + 202. 快乐数 + 1. 两数之和

《代码随想录》Day6

1. 哈希表理论基础

哈希表中关键码就是数组的索引下标,然后通过下标直接访问数组中的元素,一般遇到了要快速判断一个元素是否出现集合里的时候,就要考虑哈希法,但哈希法也是牺牲了空间换取了时间,因为我们要使用额外的数组,set或者是map来存放数据,才能实现快速的查找。

哈希函数

可以将关键码映射为哈希表的索引,后续就可以通过查询索引下标快速找到关键码

哈希碰撞

多个关键码映射到了同一索引位置,一般用拉链法或线性探测法解决

拉链法

在这里插入图片描述

线性探测法

将多余的关键码放到哈希表的空位中
在这里插入图片描述

哈希表结构

一般有三种数据结构:数组、Set(集合)、map(映射)

2. Q242.有效的字母异位词

给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。
示例 1: 输入: s = “anagram”, t = “nagaram” 输出: true
示例 2: 输入: s = “rat”, t = “car” 输出: false

排序

将s与t分别排序字母,若排序后相等则是字母异位词

class Solution:
    def isAnagram(self, s: str, t: str) -> bool:
        if sorted(s) == sorted(t):
            return True
        else:
            return False

或者直接

class Solution:
    def isAnagram(self, s: str, t: str) -> bool:
        return sorted(s) == sorted(t)

Counter() 函数

Counter()可以用来统计序列中每个元素出现的次数。

class Solution:
    def isAnagram(self, s: str, t: str) -> bool:
        s = Counter(s) #可以用来统计序列中每个元素出现的次数
        t = Counter(t)
        return s == t

defaultdict()函数

defaultdict()函数在collections包中
defaultdict(int) 可创建一个value为整数类型的字典

class Solution:
    def isAnagram(self, s: str, t: str) -> bool:
        from collections import defaultdict
        s_dict = defaultdict(int) # 创建一个value为整数类型的字典
        t_dict = defaultdict(int)
        for i in s:
            s_dict[i] +=1
        for j in t:
            t_dict[j] +=1
        return s_dict == t_dict

哈希表

  • 构建一个26位字母的数组来对字符串中出现过的字母计数
  • 利用ord()将字母转化为ASCII格式的10进制数字
    • 遍历字符串s,出现某字母则数组该字母对应位置+1
    • 遍历字符串t,出现某字母则数组该字母对应位置-1
  • 最后若数组不全为0则s和t不一致
class Solution:
    def isAnagram(self, s: str, t: str) -> bool:
        count = [0]*26
        for i in s:
            count[ord(i)-ord('a')] += 1
        for j in t:
            count[ord(j)-ord('a')] -= 1
        for i in range(26):
            if count[i] != 0:
                return False
        return True

3. Q349. 两个数组的交集

set()函数

class Solution:
    def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
        a = set(nums1) #set() 函数创建一个无序不重复元素集,重复的被删掉
        b = set(nums2)
        return list(a & b)

哈希表 - 数组

遍历数组 nums1,对于其中的每个元素,遍历数组 nums2 判断该元素是否在数组 nums2 中,如果存在,则将该元素添加到返回值。

class Solution:
    def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
        arr = [0]*1001 #因为两数组范围都为[1,1000]
        for num in nums1:
            arr[num] = 1 #储存nums1中元素
        ans = []
        for num in nums2:
            if arr[num] == 1:
                ans.append(num) #判断是否在nums2中
                arr[num] += 1 #该数字已被计算,则改变数值防止重复计算
        return ans

哈希表 - set

如果哈希值比较少、特别分散、跨度非常大,使用数组就造成空间的极大浪费。则可考虑用set,但直接使用set 不仅占用空间比数组大,而且速度要比数组慢

class Solution:
    def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
        val_dict = {} #set
        ans = []
        for num in nums1:
            val_dict[num] = 1
        for num in nums2:
            if num in val_dict.keys() and val_dict[num] ==1:
                ans.append(num)
                val_dict[num] = 0
        return ans

4. Q202. 快乐数

在这里插入图片描述

思路

- 各数位平方和的写法
1. `sum( int(i)**2  for i in str(num))`
2. 
while num:
	sum += num % 10 #取num除以10的余数,相当于取个位数
	num = num //10 #取商的整数部分,相当于每次往前一个数位
- 无限循环

算快乐数的时候有可能陷入无限循环,所以需要一个set来储存sum的结果,若sum的结果之间出现过,则代表已陷入循环

哈希表-set

我们遇到了要快速判断一个元素是否出现集合里的时候,就要考虑哈希法了,此时用record = set(),添加元素用record.add(n)

class Solution:
    def isHappy(self, n: int) -> bool:
        record = set() #创建一个set来储存结果
        sum_ = n
        while True:
            sum_ = sum(int(i)**2 for i in str(sum_)) #各数位平方和
            if sum_ in record:
                return False
            elif sum_ == 1:
                return True
            else:
                record.add(sum_)

5. Q1. 两数之和

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

暴力解法

两层for循环

class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        for i in range(len(nums)):
            for j in range(i+1,len(nums)):
                if nums[i] + nums[j] == target:
                    return  [i,j]

哈希表- map

  • 优化思路:
    用哈希表可以快速查找,可以将遍历过的元素记录在哈希表内,每次搜索时看哈希表内能否出现匹配元素,若能凑成target,则返回对应元素组下标;该方法节约了再回到nums中查找数值和索引的时间
  • 哈希表使用:
    此题中需要存两类数据,数值和索引值,所以考虑使用 map 的key value结构,key用来存元素,value用来存下标
    {key:数据元素,value:数组元素对应的下标}
    • 数组和set来做哈希法的局限。
      • 数组的大小是受限制的,而且如果元素很少,而哈希值太大会造成内存空间的浪费。
      • set是一个集合,里面放的元素只能是一个key,而两数之和这道题目,不仅要判断y是否存在而且还要记录y的下标位置,因为要返回x 和 y的下标。所以set 也不能用。
    • map中key和value分别表示什么
      • key的元素为需要判断是否出现过的元素,所以数组中数值作为key
      • 对应的value就是下标了
class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        record = {}  #{key:数据元素,value:数组元素对应的下标}
        for index, value in enumerate(nums): #遍历nums
            if target - value in record: #需查找的是target - value,即为record中的key
                return [record[target - value],index]  #若满足条件,返回对应数组对下标
            record[value] = index #将这次遍历到的元素index作为map值记入record中
        return []
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值