想躺平又躺不平的day04

哈希表理论基础

一般哈希表都是用来快速判断一个元素是否出现集合里;PS:基于哈希表的查询操作的时间复杂度为O(1)
常见的三种哈希结构:

  • 数组
  • set(集合)
  • map(映射)

  用哈希表解题最重要的是要考虑用哪种哈希结构

有效的字母异位词

给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。(s和t仅包含小写字母)注意:若 s 和 t 中每个字符出现的次数都相同,则称 s 和 t 互为字母异位词。

  解题的核心思想就是要想直到两个字符串是否为字母异位词,即统计两个字符串的字母出现次数,判断是否相等。
  由题目可知,字符串的构成均为小写字母,那么即统计26个小写字母的出现次数。对于这种元素在有限范围的,一般选用数组结构的哈希表。由于小写字母的ASCII码是连续的,那么如果a作为数组第一个元素,以此类推某个字母与a字母的ASCII码差值即为数组索引,对应的数组元素为该字母出现的次数。
  首先,定义一个长度为26的数组结构的哈希表,遍历第一个字符串,得到对应的哈希表,其中元素为这个字符串中每个字母出现的次数;接着遍历另一个字符串,每出现一次某个字母,将哈希表对应的元素减一,直到遍历完整个字符串。最后,判断哈希表的每个元素是否均为0,只要有一个元素不为0则这两个字符串不为字母异位词。

class Solution(object):
    def isAnagram(self, s, t):
        """
        :type s: str
        :type t: str
        :rtype: bool
        """
        hash_table = [0]*26
        for i in range(len(s)):
            hash_table[ord(s[i])-ord('a')] += 1  #ord()计算字符对应的ASCII码
        for j in range(len(t)):
            hash_table[ord(t[j])-ord('a')] -= 1
        for m in hash_table:
            if m != 0:
                return False
        return True

两个数组的交集

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

  交集为即在nums1中出现又在nums2中的元素,且输出的每个元素唯一。那么,只能用集合结构的哈希表或者映射结构的哈希表(python中就是字典),利用集合元素不重复或字典key不重复的特性。
  遍历一个数组得到集合或者字典类型的哈希表,再遍历另外一个数组,判断元素是否在哈希表内,在的话放入输出的集合中,并移除哈希表对应的元素;不在则继续遍历下一个元素。最后,将集合转换为列表得到最终输出。

class Solution(object):
    def intersection(self, nums1, nums2):
        """
        :type nums1: List[int]
        :type nums2: List[int]
        :rtype: List[int]
        """
        # 集合
        hash_table = set()
        for n1 in nums1:
            hash_table.add(n1)
        # 字典
       	#hash_table = {}
        #for n1 in nums1:
        #    hash_table[n1] = hash_table.get(n1,0) + 1 #dict.get(key,x)表示返回key对应的value,key不存在则返回x
        result = set()
        for n2 in nums2:
            if n2 in hash_table:
                result.add(n2)
                hash_table.remove(n2)
        return list(result)

  还有一种解法直接将两个数组转换集合,再按位与&得到交集。

class Solution(object):
    def intersection(self, nums1, nums2):
        """
        :type nums1: List[int]
        :type nums2: List[int]
        :rtype: List[int]
        """
        return list(set(nums1) & set(nums2))

  这里有一个地方就是只能用&操作而不能用and操作,and是逻辑与运算。

a = (1,2,3,4)
b = (1,2,3,4,5)
a & b # (1,2,3,4)
a and b # (1,2,3,4,5)

快乐数

判断一个数 n 是不是快乐数。 「快乐数」 定义为:

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

  本题有两个难点,一是计算该数字的每个位置上数字的平方和sum,二是该数字不为快乐数的判断条件。按题意可知,某个数为快乐数为循环若干次得到的sum为1,那么不为快乐数则为在循环过程中得到的sum在之前出现过,也就是说陷入了死循环,则表示该数字不是快乐数。

class Solution(object):
    def isHappy(self, n):
        """
        :type n: int
        :rtype: bool
        """
        hash_table = set()
        while True:
            n = self.get_num(n)
            if n == 1:
                return True
            if n in hash_table:
                return False  
            hash_table.add(n)
    def get_num(self, n):
        s = 0
        while n:
            n , r = divmod(n, 10)  # 159 , 8 = divmod(1598, 10)
            s += r ** 2
        return s

两数之和

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个
整数,并返回它们的数组下标。可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。可以按任意顺序返回答案。

  需要知道一个数组中是否存在两个元素相加等于某个值target,可以转换为遍历这个数组并把遍历过的元素存进哈希表,每往后遍历查询一次是否存在一个遍历过的元素使得两者之和为target。如果存在则返回遍历的那个元素对应的索引,不存在则把当前遍历的元素存进哈希表(如果该元素已存在则会覆盖,索引更新为该元素再次出现的索引)。然后,哈希表除了记录元素之外,还需要把元素对应的索引存进哈希表与其一一对应。所以,自然而然,我们应该选取映射结构的哈希表。

class Solution(object):
    def twoSum(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """
        hash_table = {}
        for i in range(len(nums)):
            n = target - nums[i]
            if n in hash_table: #判断当前所需要的另一数字是否出现过
                return [hash_table[n],i]
            hash_table[nums[i]] = i
        return [] 

今天的题目好多,完事状态也不是很好,陆陆续续感觉今天也没干啥就只刷了题和写博客了。明天合理安排,还要弄小论文呢。好想摆~~~

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值