代码随想录 | 哈希表题目集合

今天用一篇博客把所有的哈希表内容总结起来~~
首先,什么时候想到用哈希表呢:当需要判断一个元素是否在一个集合中时。哈希表有三种,数组,set和map,要分情况看如何使用。

242.有效的字母异位词

在这里插入图片描述
这道题很有意思,属于是不学哈希表根本想不到该怎么做的那种。

class Solution:
    def isAnagram(self, s: str, t: str) -> bool:
        record = [0] * 26
        for i in s:
            record[ord(i) - ord('a')] += 1
        for i in t:
            record[ord(i) - ord('a')] -= 1
        for i in record:
            if i != 0:
                return False
        return True

方法是创建一个数组record来作为“哈希表”。因为我们需要存储的部分,也就是字母,的个数是确定的,只有26位。那我们怎么定位到每个字母的索引呢?需要用ord(i)来找到ASCII码。最后通过判断record中是否每个字母对应的出现次数都是0即可。

349. 两个数组的交集

在这里插入图片描述
第一种方法,使用set作为哈希表来进行储存。

class Solution:
    def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
        table = {}
        for i in nums1:
            table[i] = table.get(i,0) + 1
        count = set()
        for i in nums2:
            if i in table:
                count.add(i)
                del table[i]
        return list(count)

在这种方法里,需要注意的点有以下几个:(1)table.get(i,o)这个用法很棒,指的是如果table里有一个key名为i,就取出那个key所对应的value,不然就输出0;(2)每次在count里加入了i,就要把它从table里删去,以此避免重复出现。

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

这个方法我最爱了,直接用set的函数,不带一点拖泥带水的。

class Solution:
    def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
        a = [0] * 1000
        b = [0] * 1000
        for i in nums1:
            a[i] += 1
        for i in nums2:
            b[i] += 1
        results = []
        for i in range(1000):
            if a[i] * b[i] > 0:
                results.append(i)
        return results

第三种方法是根据leetcode的新要求,nums1和nums2中的数字都不超过1000这个条件确定的。因为都不超过1000,所以可以创立两个数组a和b,在对应数字出现的时候将计数+1,这样同样的数字都出现的时候才会把它加入到最终的results中。

202.快乐数

在这里插入图片描述
这道题的关键是,要判断是否无限循环,无限循环就是和出现过的意思。因此要增加一个判断。同时还需要知道使用divmod函数,用来计算n各个位数上数字的平方和。总体来说代码如下:

class Solution:
    def isHappy(self, n: int) -> bool:
        record = set()
        while True:
            n = self.sum_n(n)
            if n == 1:
                return True
            if n in record:
                return False
            else:
                record.add(n)
    def sum_n(self, n:int) -> int:
        sum_all = 0
        while n:
            n, r = divmod(n,10)
            sum_all += r**2
        return sum_all

1. 两数之和

在这里插入图片描述
这道题在博客里也说得很清楚啦,主要就是几个点:
1)如何想到使用哈希表;2)哈希表为什么要使用map;3)如何实现哈希表;4)key和value分别存储什么。
最终的实现也很方便,可以用字典实现(key,value)对的存储,也可以用set,index就是索引,出现的位置,然后存储value。

class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        record = {}
        for index, value in enumerate(nums):
            temp = target - value
            if temp in record:
                return [record[temp], index]
            else:
                record[value] = index
        return []

6. 四数相加

在这里插入图片描述

这道题的思路很好,很多时候我们都避免用两个for循环,但是这道题偏偏就用了两个for,只要能解决问题就是好思路!

class Solution:
    def fourSumCount(self, nums1: List[int], nums2: List[int], nums3: List[int], nums4: List[int]) -> int:
        colle = {}
        for n1 in nums1:
            for n2 in nums2:
                if (n1+n2) in colle:
                    colle[n1+n2] += 1
                else:
                    colle[n1+n2] = 1
        count = 0
        for n3 in nums3:
            for n4 in nums4:
                if (-n3-n4) in colle:
                    count += colle[-n3-n4]
        return count

383. 赎金信

在这里插入图片描述
这道题不难,但是有非常多种有意思的解法。比如说collections函数中的defaltdict, counter,以及count用法等等。这次来不及啦,二刷的时候补上~~

class Solution:
    def canConstruct(self, ransomNote: str, magazine: str) -> bool:
        dic = {}
        for i in magazine:
            dic[i] = dic.get(i, 0) + 1
        for i in ransomNote:
            if i in dic and dic[i] > 0:
                dic[i] -= 1
            else:
                return False
        return True

15. 三数之和

在这里插入图片描述
这道题最重要的思路,也是最麻烦处理的地方,是不可包含重复的三元组。为了解决这个问题,需要在多个地方予以限制。也正是因为这个问题的存在,不能使用哈希,而用快慢指针来完成。
需要注意的,首先是i和左边的不相同,然后是left和右边、right和左边不相同。

class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        result_all = []
        nums.sort()
        for i in range(len(nums)):
            if nums[i] > 0:
                return result_all
            if i > 0 and nums[i] == nums[i-1]:
                continue

            left, right = i+1, len(nums)-1
            while left < right:
                result = nums[left] + nums[right] + nums[i]
                if result > 0:
                    right -= 1
                elif result < 0:
                    left += 1
                else:
                    result_all.append([nums[i], nums[left], nums[right]])
                    while left < right and nums[left] == nums[left+1]:
                            left += 1
                    while left < right and nums[right] == nums[right-1]:
                            right -= 1
                    left += 1
                    right -= 1
        return result_all

18. 四数之和

在这里插入图片描述
好耶!!这道题是自己写出来的,开心呜呜呜呜。剪枝操作本身可有可无,在大规模方面的优化领域是有意义的,在力扣里可以省去。需要注意一些细节思路都很清晰。

class Solution:
    def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
        nums.sort()
        result = []
        for i in range(len(nums)):
            #以下两行为剪枝操作,可以省略
            if nums[i] > target and nums[i] > 0 and target >0:
                return result
            if i > 0 and nums[i] == nums[i-1]:
                continue
            for j in range(i+1, len(nums)):
                #以下两行为剪枝操作,可以省略
                if (nums[j] > target - nums[i]) and (target > 0):
                    break
                if j > i+1 and nums[j] == nums[j-1]:
                    continue
                left, right = j+1, len(nums) - 1
                while left < right:
                    s = nums[i] + nums[j] + nums[left]+ nums[right]
                    if s < target:
                        left += 1
                    elif s > target:
                        right -= 1
                    else:
                        result.append([nums[i], nums[j], nums[left], nums[right]])
                        while left<right and nums[left] == nums[left+1]:
                                left += 1
                        while left<right and nums[right] == nums[right-1]:
                                right -= 1
                        left += 1
                        right -= 1
        return result

总结一下!哈希表有三种:数组、set和map。
数组是在出现元素固定的时候比较常用,set则更倾向于不重复元素,而对于map来说则是需要key和value共同出现的时候使用比较合适。
二刷的时候要理解得更深入一些!!!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值