研习代码day5| 快速判断元素是否出现集合中 --> 哈希法

一、有效的字母异同词

        1.1 题目

        给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。

        注意:若 s 和 t 中每个字符出现的次数都相同,则称 s 和 t 互为字母异位词。

        示例 1:

        输入: s = "anagram", t = "nagaram"
        输出: true

        示例 2:

        输入: s = "rat", t = "car"
        输出: false

        提示: s 和 t 仅包含小写字母

        1.2 题目链接

        242. 有效的字母异位词

        1.3 解题思路和想法

        解题思路:借用哈希数组记录字符串中字符的情况,一个用增加数组值的方式记录,另一个用减少数组值的方式记录。若最终存在数组值不为0的情况,则表明二者的字母构成不同。

        想法:

        (1)最初想用字典来存储字符串的构成,卡了一下判断的条件(对python不是很熟悉)。

        (2)感觉上述解题思路中因为题目限制了数值的大小----->用数组构造哈希会很简单,并且利用差值来判断的方式很巧妙。

        (3)这道题如果使用库函数的话,或许有更简单的方式,但我以后并不会以python为主要编程语言,只是近期在学习机器学习而已,所以此处并未写出这类解法。

        1.4 代码

                1.4.1 数组--->哈希
class Solution:
    def isAnagram(self, s: str, t: str) -> bool:
        # 用哈希表记录字符串的字母情况,对应关系:'x' 的下标---> 'x' - 'a',用数组的值存储字母的情况
        words = [0] * 26

        # c++中可直接用 i-'a',python需用 ord(i)-ord('a')
        for i in s:
            index = ord(i)-ord('a')
            words[index] += 1

        # 若在 s 和 t 中同时出现,则在统计 t 时-1,便于后续统计二者差距
        for i in t:
            index = ord(i)-ord('a')
            words[index] -= 1

        for i in range(26):
            if words[i] != 0:
                return False
            
        return True
        1.4.2 字典--->哈希
class Solution:
    def isAnagram(self, s: str, t: str) -> bool:
        # 用字典构造两个哈希表
        hash_s = dict()
        hash_t = dict()
        # 初始化最终结果为True
        flag = True

        # 通过遍历,用哈希表记录字符串内部构成
        for i in s:
            if not hash_s.get(i):
                hash_s[i] = 1
            else:
                hash_s[i] += 1
        
        for j in t:
            if not hash_t.get(j):
                hash_t[j] = 1
            else:
                hash_t[j] += 1

        # 通过遍历,判断s中的,t是否有
        for key in hash_s:
            if not hash_t.get(key) or hash_t[key] != hash_s[key]:
                return False
        
        # 通过遍历,判断t中的,s是否有
        for key in hash_t:
            if not hash_s.get(key) or hash_t[key] != hash_s[key]:
                return False
        
        return True

二、两个数组的交集

        2.1 题目

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

示例 1:

输入:nums1 = [1,2,2,1], nums2 = [2,2]
输出:[2]

示例 2:

输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出:[9,4]
解释:[4,9] 也是可通过的

提示:

  • 1 <= nums1.length, nums2.length <= 1000
  • 0 <= nums1[i], nums2[i] <= 1000

        2.2 题目链接

        349. 两个数组的交集

        2.3 解题思路和想法

        解题思路:

                用数组/字典构建哈希表,若元素同时存在于两个哈希表中,则追加至结果中。

        想法:

                (1)首先想过用数组来实现哈希,且题目限制了数值的大小,但数值为1000,不是首选但简单。

                (2)比较自然的会想到用字典来实现哈希。(为避免重复统计,及时更新原哈希表)

        2.4 代码

                2.4.1 数组--->哈希表

class Solution:
    def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
        # 用数组构建两个哈希表
        words1 = [0] * 1001
        words2 = [0] * 1001
        # 用来存储最终结果
        res = []

        length1 = len(nums1)
        length2 = len(nums2)
        # 用遍历记录两个数组的元素情况
        for i in range(length1):
            words1[nums1[i]] += 1
        
        for j in range(length2):
            words2[nums2[j]] += 1
        
        # 判断元素是否同时出现在两个数组中
        for k in range(1001):
            if words1[k] and words2[k]:
                res.append(k)
        
        return res

                2.4.2 字典--->哈希表

class Solution:
    def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
        # 用字典构建存储列表内部情况的哈希表,用列表存储最终结果
        hash = dict()
        res = []

        # 通过遍历的方式,用哈希表记录 nums1 中的构成
        for i in nums1:
            if not hash.get(i):
                hash[i] = 1

        # 在遍历 nums2 的过程中,判断 nums1 中是否也存在对应元素。若存在,则追加至res中,并更新哈希表(避免重复统计)
        for j in nums2:
            if hash.get(j):
                res.append(j)
                hash[j] = 0

        return res        

三、快乐数

        3.1 题目

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

「快乐数」 定义为:

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

如果 n 是 快乐数 就返回 true ;不是,则返回 false 。

示例 1:

输入:n = 19
输出:true
解释:
12 + 92 = 82
82 + 22 = 68
62 + 82 = 100
12 + 02 + 02 = 1

示例 2:

输入:n = 2
输出:false

提示:

  • 1 <= n <= 2^31 - 1

        3.2 题目链接

                202. 快乐数

        3.3 解题思路和想法

       解题思路:利用该数变换过程中的规律,只要变换过程中出现重复的数字且不为1,则不为快乐数。用字典构造哈希,用来快速判定当前数字是否已存在于哈希表中。

        想法:刚看到题目的时候有点懵,心想这是数学题?没关注到题目给的提示-------“重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1”。

        心得:当遇到了要快速判断一个元素是否出现集合里的时候,就要考虑哈希法了!!!

        3.4 代码

class Solution:
    # 算出当前数的各数位的平方和
    def new(self,n:int) -> int:
        sum = 0
        while n > 0:
            m = n % 10
            sum += m ** 2
            n = n // 10
        
        return sum
    
    def isHappy(self, n: int) -> bool:
        # 如果int = 9999999999999,各位数的平方和为 1053 ,表明数不会越来越大
        # 结合题中描述,如果不是快乐数,过程中数字会出现循环这一现象------>判断是否出现数字再现且数字不为1的情况
        # 当遇到了要快速判断一个元素是否出现集合里的时候,就要考虑哈希法了。

        # 初始化结果是True,只要后续出现数字重复且不为1的情况,则修改 flag
        flag = True
        # 用字典构建哈希
        hash = dict()
        # 目前的数字
        cur = n

        # 判断新生成的数是否重复且不为1
        while cur != 1 :
            if not hash.get(cur):
                hash[cur] = 1
                # 及时更新cur
                cur = self.new(cur)
            else:
                flag = False
                break

        return flag

四、两数之和

        4.1 题目

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

        你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。

        你可以按任意顺序返回答案。

示例 1:

输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。

示例 2:

输入:nums = [3,2,4], target = 6
输出:[1,2]

示例 3:

输入:nums = [3,3], target = 6
输出:[0,1]

提示:

  • 2 <= nums.length <= 104
  • -109 <= nums[i] <= 109
  • -109 <= target <= 109
  • 只会存在一个有效答案

        4.2 题目链接

        1. 两数之和

        4.3 解题思路和想法

        思解题路:在一堆数中快速判断某数是否存在----> 哈希法。用字典构造哈希表(以值为key,以索引为value),结合题中所给条件:(1)数不重复(2)每种输出只对应一个答案(3)下标为一对;通过一次遍历,先判断 target-x 是否存在于哈希表中(存在则终止循环,输出结果),否则将该数存入哈希表中。

        想法:思考的过程比较顺畅,只是最初没想到只用一次遍历(没想着利用数是一对),并且在判断条件中 hash.get(target - value)  可能为零的情况下卡顿了一下。

        4.4 代码

class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        # 快速判断元素是否出现集合中 --> 哈希法

        # 用字典构建哈希表
        hash = dict()
        # 初始化目的列表
        res = []

        # 先通过遍历,将所有数字加入到哈希表中(题设:数组中无重复数),并同时查找符合条件的下标
        # (下标为一对,第一个没搜到,另一个若满足一定会被搜到,所以可以共用一趟遍历)
        # 在得到当前数 x 的情况下,在哈希表中查找 target-x 是否存在
        for index,value in enumerate(nums):
            # 不能直接写 if hash.get(target - value): 因为可能获取的值的下标就是0
            if target - value in hash:
                res.append(index)
                res.append(hash.get(target - value))
                break
            else:
                # 应先判断,若不满足条件再加入,否则 当 target=6 ,value=3 时,会误搜索到当前数3的index
                hash[value] = index
        return res
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值