Day05 今日再看哈希,能看出什么咧

据说要熟悉下定义,检索下检索下~

哈希表中关键码就是数组的索引下标,然后通过下标直接访问数组中的元素

那么哈希表能解决什么问题呢,一般哈希表都是用来快速判断一个元素是否出现集合里。

例如要查询一个名字是否在这所学校里。

要枚举的话时间复杂度是O(n),但如果使用哈希表的话, 只需要O(1)就可以做到。

将学生姓名映射到哈希表上就涉及到了hash function ,也就是哈希函数

哈希表的内部实现原理:哈希表的内部实现原理是利用哈希函数将键映射到存储桶(buckets)的索引上,从而实现高效的数据查找和插入操作。哈希函数将键转换为一个固定大小的哈希值,然后通过取模运算将哈希值映射到存储桶的索引上。

哈希函数是将输入(键)映射到固定大小的输出(哈希值)的函数。好的哈希函数应该具有以下特性:

  • 一致性:对于相同的输入,始终产生相同的哈希值。
  • 均匀性:尽可能均匀地将不同的输入映射到不同的哈希值,以减少哈希碰撞的概率。
  • 高效性:计算速度快,适用于大规模数据。

哈希碰撞是指不同的键经过哈希函数计算后得到相同的哈希值,导致它们被映射到哈希表中的同一个存储桶。哈希碰撞是不可避免的,因为哈希函数的输出空间通常要远小于输入空间的大小。解决哈希碰撞的常见方法包括开放地址法、链地址法和再哈希法等。

常见的哈希表有数组、Set和Map。它们的区别如下:

  • 数组:使用整数作为索引,将值存储在对应的数组位置上。数组可以看作是一种简单的哈希表,哈希函数即为索引计算函数。在数组中,键和值之间的映射是直接的,没有额外的数据结构。
  • Set:Set是一种无重复元素的集合,它存储的是键的集合而不存储对应的值。Set使用哈希表来实现,通过哈希函数将键映射到存储桶中,以支持高效的查找和插入操作。
  • Map:Map是一种键值对的映射结构,它存储的是键值对的集合。Map也使用哈希表来实现,通过哈希函数将键映射到存储桶中,并将值与键关联起来。

 242.有效的字母异位词 

1、数组方法~ 可以使用数组来实现简单的哈希表,其中数组的索引表示哈希值,数组元素存储对应的值。这种实现适用于哈希值的范围较小且连续的情况。

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

2、敲敲,这题集合(Set)方法不合适,集合(Set)是由一组唯一旦无序的元素组成的数据结构。集合中的元素不能重复,且没有特定的顺序。集合通常用干判断元素的存在性和去重操作。

但这题不仅是元素存在,还有频次得问题,可以用字典~

PS. 字典(Dictionary)是由键-值对(Key-Value Pair)组成的数据结构。每个键(Key)都是唯一的,而值(Value)可以重复。字典通常用于存储和检索具有对应关系的数据。

代码中的char_freq是一个字典(dictionary),用于保存字符串s中每个字符出现的频率。字典的键(key)是字符,值(value)是该字符在字符串s中出现的次数。

class Solution:
    def isAnagram(self, s: str, t: str) -> bool:
        if len(s) != len(t):
            return False

        char_freq={}

        for char in s:
            if char in char_freq:
                char_freq[char]+=1
            else:
                char_freq[char]=1
        for char in t:
            if char in char_freq and char_freq[char]>0:
                char_freq[char]-=1
            else:
                return False
        return True

 349. 两个数组的交集 

给定两个数组 nums1 和 nums2 ,返回 它们的交集。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。

1、数组方法

# 错误记录: 这样写如果在nums1或nums2中由重复元素,无法正确识别,感觉还是集合合适。

class Solution:
    def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
        ## 数组方法
        res=[0]*10

        result=[]
        for i in range(len(nums1)):
            res[nums1[i]]+=1

        for i in range(len(nums2)):
            res[nums2[i]]+=1

        for i in range(10):
            if res[i]>=2:
                result.append(i)

        return result

数组暂时没想到啥,记录次数好像复杂了,集合就可以判断在不在。

class Solution:
    def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
        # 集合方法
        n1=set(nums1)
        n2=set(nums2)
 
        result=[]

        for i in n1:
            if i in n2:
                result.append(i)
        return result

第202题. 快乐数

编写一个算法来判断一个数 n 是不是快乐数。

「快乐数」定义为:对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和,然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。如果 可以变为  1,那么这个数就是快乐数。

如果 n 是快乐数就返回 True ;不是,则返回 False 。

想说,这种啊,新的定义就要想想,不过判断一个数 n 是不是快乐数读题其实有点哈希的意思的。

最开始339 / 420 个通过的测试用例,我服气的。n =1 好吧,我忘了,修改了

class Solution:
    def isHappy(self, n: int) -> bool:
        record=set()


        while 1 not in record and n != 1:
            n=self.squaresSum(n)
            
            if n==1:
                return True
            if n in record:
                return False
            else:
                record.add(n)
        return True
    
    # 定义一个函数去求每个位置的平方和吧
    def squaresSum(self,n):
        sum=0
        while n:
            sum+=(n%10)**2
            n=n//10
        return sum
        

1. 两数之和

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

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。

找数组下标比较头疼,不过不难,嵌套下就好

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

完工,电脑死了两次,辛苦它了,最近霍霍的有点严重。

  • 12
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值