leetcode刷题——哈希表

一、认识哈希表

  • 数组本质上就是一张哈希表(也称为散列表),哈希表只不过把数组的索引显式表示出来了。所以数组和哈希表查询的时间复杂度都是O(1),一般会用来快速判断一个元素是否在集合中。其添加和删除的时间复杂度是O(n),因为删除或者添加一个元素后面的元素要补上去。
  • 与之相对应的是链表,删除和添加的时间复杂度是O(1),查询是O(n),因为最坏的情况是要一直查找到最后一个元素。

二、哈希表的作用

  • 统计字符串中所有元素的个数
  • 根据唯一索引(分类标志),来存储对应的属于同一组的元素

三、哈希法

  • 适用哈希法,一般会选择以下数据结构:set(集合)、字典、数组:【异位词】
  • 哈希法查找实际是牺牲时间换取空间,因为需要额外的数组、set或者字典来存储数据,才能实现快速的查找。【异位词组】

四、例题

(一)找重合

242. 有效的字母异位词

  • 实质:判断双序列元素及元素个数是否一致

调包

class Solution:
    def isAnagram(self, s: str, t: str) -> bool:
        from collections import Counter
        return Counter(s)==Counter(t)

一个哈希表

class Solution:
    def isAnagram(self, s: str, t: str) -> bool:
        # 先对s的所有字母构建字典,再根据t的构成对这个字典判断个数是否正确
        hash=dict()
        for i in s:
            if i in hash:hash[i]+=1 # 如果在就累加1,如果不在就返回0
            else:hash[i]=1
        
        for j in t:
            if j in hash:hash[j]-=1  # 在就-1,不在就返回1
            else:return False
        # 判断最后字典的value中是否有非零元素
        for value in hash.values():
            if value!= 0:return False
        return True

两个哈希表判断是否相等

class Solution:
    def isAnagram(self, s: str, t: str) -> bool:
        from collections import defaultdict
        
        s_dict = defaultdict(int)  # 如果key不存在时,则默认返回0
        t_dict = defaultdict(int)

        for x in s:
            s_dict[x] += 1
        
        for x in t:
            t_dict[x] += 1

        return s_dict == t_dict

49. 字母异位词分组

判断两个单词是否互为异位词>>判断一群单词中的异位词对,并用列表的形式存储起来

【法一】defaultdict(list)
  • 思路:可以用defaultdict(list)的结构来存储满足相同条件的元素都存储在同一列表中的要求,最后返回list(res.values())来呈现出列表中的列表形式
class Solution:
    def groupAnagrams(self, strs: List[str]) -> List[List[str]]:
        # 可以用defaultdict(list)的结构来存储列表中的列表格式
        res=collections.defaultdict(list)
        # 将所有单词排序,并以排序后的单词为key,来存储单词
        for str in strs:
            key=''.join(sorted(str))
            res[key].append(str)   # 字典中value为列表
        return list(res.values())

349. 两个数组的交集

class Solution:
    def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
        set1,set2=set(nums1),set(nums2)
        return list(set1&set2)

350. 两个数组的交集 II
【法一】交集,之后统计元素个数

class Solution:
    def intersect(self, nums1: List[int], nums2: List[int]) -> List[int]:
        set1,set2=set(nums1),set(nums2)
        intersection=list(set1&set2)   # 先得到元素
        res=[]
        for i in intersection:  # 再扩充元素的个数
            n=min(nums1.count(i),nums2.count(i))
            res=res+([i]*n)
        return res

【法二】先对一个列表计数,然后遍历另一个,更正交集元素的个数,同时也录入交集元素。

  • 代码技巧:为了节省时间,先对短的列表进行计数,因为计数对每个字符都要遍历n次。然后在统计交集元素个数的时候,对另一个列表的每个元素遍历,取最小(用减一法)
class Solution:
    def intersect(self, nums1: List[int], nums2: List[int]) -> List[int]:
        if len(nums1)>len(nums2):
            nums1,nums2=nums2,nums1
        from collections import Counter
        counter_1=Counter(nums1)   # 假设nums1是短列表
        res=[]

        # 判断一个字典中的元素是否在另一个中,并找到最小的个数
        for key in nums2:
            if key in counter_1 and counter_1[key]>0:
                res.append(key)
                counter_1[key]-=1   # key是数字,value是个数
            else:continue
        return res
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值