代码随想录算法训练营-哈希表章节

Leetcode 刷题记录 Day5

哈希表数组理论

哈希表: 哈希表中关键码就是数组的索引下标,然后通过下标直接访问数组中的元素, 其实数组就是一个哈希表。哈希表通常用于快速判断某个元素是否在表中, O(1)。

哈希函数(hash function):ex. 找学生名字是否在学校中哈希函数。Hash Function把学生的姓名直接映射为哈希表上的索引,然后就可以通过查询索引下标快速知道这位同学是否在这所学校里了。

如果hashCode得到的数值大于 哈希表的大小了,也就是大于tableSize了,怎么办呢?

此时为了保证映射出来的索引数值都落在哈希表上,我们会在再次对数值做一个取模的操作,这样我们就保证了学生姓名一定可以映射到哈希表上了。

哈希碰撞: 

        拉链法:

        线性探索法:

常见哈希结构:  

  • list
  • set
  • map/dictionary

总结: 当我们需要快速寻找一个目标是否在集合中, 就要考虑哈希表

242. Valid Anagram

目标: 判断是否由相同字符构成

哈希法解题: 三种常见哈希表(数组, set, map)

a - z, 总共26个小写字符, 利用ASCII码 由于是连续的a对应到0,b对应到1, etc.

利用 ord('x') - ord('a')得到x的order;

定义数组长度为26, 用于记录第一个数组每个字符出现哦频率, 第二个数组进行扣减, 最后数组都为0则True

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

349. Intersection of Two Arrays

为什么用哈希表? 哈希表擅长于解决判断元素是否在集合中出现

class Solution:
    def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
        # 使用dictionary解决
        hash = {}
        for n1 in nums1:
            hash[n1] = hash.get(n1, 0) + 1
        res = []
        for n2 in nums2:
            if n2 in hash:
                res.append(n2)
                del hash[n2]
        return res

202. Happy Number

重点是: 如果不是Happy Number, 会无限循环,那么也就是说求和的过程中,sum会重复出现,这对解题很重要!

class Solution:
    def isHappy(self, n: int) -> bool:
        def get_sum(n):
            s = 0
            for i in str(n):
                s += int(i) ** 2
            return s
        hash = set()
        while True:
            n = get_sum(n)
            if n == 1:
                return True
            if n in hash:
                return False
            hash.add(n)

1.  Two Sum

使用Hash表是因为在遍历这个list时, 寻找是否已经遇过这个值, hash表中存储这个值以及对应index。使用dictionary, key是值, value是index

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

454. Four Sums II

四个元素中各选一个加起来为0的组合有多少(不去重)

为什么用哈希表? 将所有nums1, nums2的组合计入hash map, 然后判断nums3 nums4里的元素和是否有-num1-nums2的元素, 讲count加起来。使得时间复杂度为O(n^2)

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

383. Ransom Note

class Solution:
    def canConstruct(self, ransomNote: str, magazine: str) -> bool:
        word_count = [0] * 26
        for s in magazine:
            word_count[ord(s) - ord('a')] += 1
        for r in ransomNote:
            if word_count[ord(r) - ord('a')] >= 1:
                word_count[ord(r) - ord('a')] -= 1
            else:
                return False
        return True

15. 3Sum

哈希法去重操作过于复杂

使用三指针法:

先排序

i遍历0 -> len(nums) - 3的位置, left初始为i + 1, right为len(nums) - 1

如何更新left, right?和大于0 缩小right, 小于0 增加left, 等于0 记入result并同时更新left, right

class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        def move_left(nums, l, r):
            while r > l and nums[l] == nums[l + 1]:
                l += 1
            l += 1 
            return l

        def move_right(nums, l, r):
            while r > l and nums[r] == nums[r - 1]:
                r -= 1
            r -= 1 
            return r

        res = []
        nums.sort()
        i = 0
        while i < len(nums) - 2:
            l, r = i + 1, len(nums) - 1
            while l < r:
                temp_sum = nums[i] + nums[l] + nums[r]
                if temp_sum > 0:
                    r = move_right(nums, l, r)
                elif temp_sum < 0:
                    l = move_left(nums, l, r)
                else:
                    res.append([nums[i], nums[l], nums[r]])
                    r = move_right(nums, l, r)
                    l = move_left(nums, l, r)
            while nums[i] == nums[i + 1] and i < len(nums) - 2:
                i += 1
            i += 1
        return res



18. 4Sum

与上题方法一样, 双指针但多了一层循环

class Solution:
    def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
        nums.sort()
        res = []
        a = 0
        while a < len(nums) - 3:
            b = a + 1
            while b < len(nums) - 2:
                c = b + 1
                d = len(nums) - 1
                while c < d:
                    temp_sum = nums[a] + nums[b] + nums[c] + nums[d]
                    if temp_sum < target:
                        c += 1
                        while c < d and nums[c] == nums[c - 1]:
                            c += 1
                    elif temp_sum > target:
                        d -= 1
                        while c < d and nums[d] == nums[d + 1]:
                            d -= 1
                    else:
                        res.append([nums[a], nums[b], nums[c], nums[d]])
                        c += 1
                        while c < d and nums[c] == nums[c - 1]:
                            c += 1
                        d -= 1
                        while c < d and nums[d] == nums[d + 1]:
                            d -= 1
                b += 1
                while b < len(nums) - 2 and nums[b] == nums[b - 1]:
                    b += 1
            a += 1
            while a < len(nums) - 3 and nums[a] == nums[a - 1]:
                a += 1
        return res

好累😫

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值