力扣刷题-python-哈希表(数组、set(集合)、map(dict字典))

本文介绍了哈希表的基础知识,包括定义、哈希函数和哈希碰撞的解决方法。通过实例展示了数组、集合和字典作为哈希表在LeetCode题目中的应用,如有效字母异位词、赎金信、字母异位词分组等。同时,文章还探讨了双指针操作在解决三数之和、四数之和问题中的运用。总结了哈希表在快速索引场景中的重要性,并给出了相关代码实现。
摘要由CSDN通过智能技术生成

1.哈希表(hash table)基础

之前没有对哈希表做过系统性的学习,现在各部分主要内容截图下,方便以后自己翻阅查找。
1)定义

2)哈希函数

3)哈希碰撞
因为储存时候出现两个以上的数值映射到同一个位置上,就产生了哈希碰撞,不过哈希碰撞是可以解决的,可以用拉链法和线性试探法。
拉链法

线性探测法

3)常见哈希结构

  1. 数组
  2. set(集合)
  3. map(映射)-py里面竟然是dict (字典)
    py中的set为无序的不可重复的key。
    字典包含key和value

在这里插入图片描述

2.数组作为哈希表(242、383、49、438)

242. 有效的字母异位词 - 力扣(LeetCode) (leetcode-cn.com)

class Solution(object):
    def isAnagram(self, s, t):
        """
        :type s: str
        :type t: str
        :rtype: bool
        """
        if len(s) !=len(t): return False
        hash= [0]*26
        for i in range(len(s)):
              hash[ord(s[i])-ord('a')]+=1
              hash[ord(t[i])-ord('a')]-=1

        if any ([_ for _ in hash]):return False
        else : return True

383. 赎金信 - 力扣(LeetCode) (leetcode-cn.com)

class Solution(object):
    def canConstruct(self, ransomNote, magazine):
        """
        :type ransomNote: str
        :type magazine: str
        :rtype: bool
        """
        array= [0]*26
        for i in magazine:  #+1
             array[ord(i)-ord('a')]+= 1
        for i in ransomNote:  #-1
            array[ord(i)-ord('a')]-= 1   
        if any([_<0 for _ in array]):return False
        else: return True

49. 字母异位词分组 - 力扣(LeetCode) (leetcode-cn.com)
应用了字典,

class Solution(object):
    def groupAnagrams(self, strs):
        """
        :type strs: List[str]
        :rtype: List[List[str]]
        """

        dic, ls ={}, []  #从小到排列的字符串作为key 原始的字符串作为value

        for s in strs:
            ls= ''.join(sorted(s))
            if ls in dic:  #注意不要再dic.value 里面寻找 这样会很慢 可以直接在dic里面寻找
                dic[ls].append(s)
            else:
                dic[ls]=[s]
        return list(dic.values())

438. 找到字符串中所有字母异位词 - 力扣(LeetCode) (leetcode-cn.com)

class Solution(object):
    def findAnagrams(self, s, p):
        """
        :type s: str
        :type p: str
        :rtype: List[int]
        """
        n, m, res = len(s), len(p), []
        if n < m: return res
        pCnt = [0] * 26
        sCnt = [0] * 26

        for i in range(m):  #初始窗口
            pCnt[ord(p[i])-ord('a')]+=1
            sCnt[ord(s[i])-ord('a')]+=1
        if sCnt == pCnt: res.append(0)

        for i in range(m,n):
            sCnt[ord(s[i-m])-ord('a')]-=1 #移动窗口
            sCnt[ord(s[i])-ord('a')]  +=1
            if sCnt == pCnt: res.append(i-m+1)
        return res

350. 两个数组的交集 II - 力扣(LeetCode) (leetcode-cn.com)
很意外竟然可以这样

class Solution(object):
    def intersect(self, nums1, nums2):
        """
        :type nums1: List[int]
        :type nums2: List[int]
        :rtype: List[int]
        """
        #用数组
        array = [0]*1000  #代表0-1000
        res=[]
        for i in nums1:array[i] +=1

        for i in nums2:
            if array[i] :
                array[i] -=1
                res.append(i)
        return res

2.集合作为哈希表(349、202)

349. 两个数组的交集 - 力扣(LeetCode) (leetcode-cn.com)

class Solution(object):
    def intersection(self, nums1, nums2):
        """
        :type nums1: List[int]
        :type nums2: List[int]
        :rtype: List[int]
        """
        '''
        set1= set(nums1)
        set2= set()
        
        for i in nums2:
            if i in set1  and i not in set2:
                set2.add(i)
        return list(set2)
        '''

        return list(set(nums1)& set(nums2))

202. 快乐数 - 力扣(LeetCode) (leetcode-cn.com)

class Solution(object):
    def isHappy(self, n):
        """
        :type n: int
        :rtype: bool
        """
        collet=set([n])
        while 1:
             sum=0           #%题设的循环计算
             while n:
                 sum+= (n%10)**2
                 n=n//10
             n=sum

             if n==1: return True  #快乐数
             elif n not in collet: collet.add(n)
             else: return False    #出现重复 不是快乐数

2.map(dict)作为哈希表(1、)

1. 两数之和 - 力扣(LeetCode) (leetcode-cn.com)

```python class Solution: def twoSum(self, nums: List[int], target: int) -> List[int]: dic= dict() for idx, value in enumerate(nums): #获取索引和数值 if target- value not in dic: dic[value] =idx else: return [dic[target- value], idx] ``` [454. 四数相加 II - 力扣(LeetCode) (leetcode-cn.com)](https://leetcode-cn.com/problems/4sum-ii/submissions/) 四数相加可以分别分成两个,前面两个数和只需要表示出现的次数即可,因为是要求出现的次数。 ![在这里插入图片描述](https://img-blog.csdnimg.cn/2de4d7925c894cd59e3ea6a207c26ce8.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5pyX6aOO6aOO,size_20,color_FFFFFF,t_70,g_se,x_16)
class Solution:
    def fourSumCount(self, nums1: list[int], nums2: list[int], nums3: list[int], nums4: list[int]) -> int:

        hashmap= dict()

        for i in nums1:   #将前两个数相加和作为key value表示出现的次数
            for j in nums2:
                sumls= i+j
                if sumls in hashmap:
                    hashmap[sumls]+= 1
                else:
                    hashmap[sumls] = 1
        count=0     
        for i in nums3:   #将后面两个数取相加负,看是否等于hash的key,如果等于计数加上出现的value
            for j in nums4:           
                sumls= -i-j
                if sumls in hashmap:
                    count+= hashmap[sumls]
        return count

3.双指针操作

15. 三数之和 - 力扣(LeetCode) (leetcode-cn.com)
乱入双指针操作。。

class Solution:
    def threeSum(self, nums: list[int]) -> list[list[int]]:
        #双指针法
        nums.sort()
        res=set()
        n= len(nums)
        for i  in range(n):
            if nums[i] > 0:break        
            if i >= 1 and nums[i] == nums[i- 1]:continue
            left, right = i+1,  n-1
            while left < right :
                if nums[left] +nums[right] +nums[i]> 0:
                     right-= 1
                elif nums[left] +nums[right] +nums[i]< 0:
                     left+= 1
                else:
                     #if [nums[i],nums[left],nums[right]] not in res:
                     res.add((nums[i],nums[left],nums[right]))  #用集合加元组消除重复
                     right-= 1
                     left+= 1
        return [list(_) for _ in res]

18. 四数之和 - 力扣(LeetCode) (leetcode-cn.com)

class Solution:
    def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
        #双指针法
        nums.sort()
        res=set()
        n= len(nums)

        for i  in range(n):
            if nums[i] > target//4:break        #最小的数值大于平均值 是要跳出循环的
            if i >= 1 and nums[i] == nums[i- 1]:continue  #当前数为前面的重复数
            for j in range(i+1,n):
                left, right = j+1,  n-1
                while left < right :
                    if nums[left] +nums[right] +nums[i]+nums[j]> target:
                        right-= 1
                    elif nums[left] +nums[right] +nums[i]+nums[j]< target:
                        left+= 1
                    else:
                         res.add((nums[i],nums[j],nums[left],nums[right]))  #用集合加元组消除重复
                         right-= 1
                         left+= 1
        return [list(_) for _ in res]

4.总结

需要快速索引的,可以用哈希表,哈希表有三种,数组,set(集合),map(dict字典)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值