Day06 哈希表 | 242.有效的字母异位词、349. 两个数组的交集、202. 快乐数、1. 两数之和

知识准备

  • 哈希表:用来快速判断一个元素是否出现在集合里,数组就是一张哈希表。
  • 哈希函数:存储位置(索引)与元素之间存在一个对应关系f,使每个元素key对应一个索引f(key),关系f称为哈希函数,index = f(key)。
  • 哈希碰撞:两个不同的元素拥有同一个索引。解决办法:
    1. 链地址法:把发生索引位置冲突的元素储存在链表中,通过该索引找到链表。
    2. 线性探测法:寻找下一个空的地址。要求哈希表大小大于数据量的大小。

LeetCode 242 有效的字母异位词

题目描述

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

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

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

思路

  • 创建一个长为26的全0数组
  • 遍历字符串s,每个字母对应位置的值+1
  • 遍历字符串t,每个字母对应位置的值-1
  • 若最后数组仍全为0,则表明s和t互为字母异位词
  • 如何计算字母在数组对应的位置:index = ord(s[i]) - ord(‘a’),ord函数是Python中的一个库函数,用于获取字符的ASCII值

代码

def isAnagram(self, s, t):
        """
        :type s: str
        :type t: str
        :rtype: bool
        """
        record = [0 for _ in range(26)]
        for i in range(len(s)):
            record[ord(s[i]) - ord('a')] += 1 #ord函数是Python中的一个库函数,用于获取字符的ASCII值
        for i in range(len(t)):
            record[ord(t[i]) - ord('a')] -= 1
        if record.count(0) == 26:
            return True
        else:
            return False

LeetCode 349 两个数组的交集

题目描述

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

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

思路

  1. 方法1:

    • 遍历nums1的所有元素,与nums2的所有元素作比较
    • 值相等的元素存入新数组,去除重复元素

    在Python中,可以使用set来去除数组中的重复元素。set是一个无序的不重复元素序列。

    def remove_duplicates(nums):

    return list(set(nums))

    # 测试

    print(remove_duplicates( [1, 2, 2, 3, 4, 4, 5])) # 输出:[1, 2, 3, 4, 5]

  2. 方法2:

    • 用两个数组(哈希表)记录nums1,nums2的元素数量
    • 对比两个哈希表的元素状态

代码

# method 1
class Solution(object):
    def intersection(self, nums1, nums2):
        """
        :type nums1: List[int]
        :type nums2: List[int]
        :rtype: List[int]
        """
        res = []
        for i in range(len(nums1)):
            if nums1[i] in nums2:
                res.append(nums1[i])
        return list(set(res))
        
        # method 1.5
        # return list(set(nums1) & set(nums2))
# method 2
class Solution(object):
    def intersection(self, nums1, nums2):
        """
        :type nums1: List[int]
        :type nums2: List[int]
        :rtype: List[int]
        """
        count1 = [0 for _ in range(1001)]
        count2 = [0 for _ in range(1001)]
        res = []
        for i in range(len(nums1)):
            count1[nums1[i]] += 1
        for i in range(len(nums2)):
            count2[nums2[i]] += 1
        for i in range(1001):
            if count1[i] != 0 and count2[i] != 0:
                res.append(i)
        return res

LeetCode 202 快乐数

题目描述

编写一个算法来判断一个数 n 是不是快乐数。「快乐数」 定义为:

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

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

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

思路

  • 把整数的每一位转化为列表,遍历列表求各位的平方和,并循环直至结果等于1
  • 创建一个标记列表flag,用于记录结果为一位数的次数,初始值为0;当某一位的结果为2时,说明出现了无限循环

代码

# method 1
class Solution(object):
    def isHappy(self, n):
        """
        :type n: int
        :rtype: bool
        """
        flag = [0 for _ in range(9)]
        while n != 1:
            s = [int(digit) for digit in str(n)]
            sum = 0
            for i in range(len(s)):
                sum += s[i] ** 2
            n = sum
            if n < 10:
                flag[n-1] += 1
                if flag[n-1] == 2:
                    break
        if n==1:
            return True
        else:
            return False
# method 2
'''
record记录的范围放宽到所有结果,而不仅仅是一位数时,此方法更省时间
'''
class Solution:
   def isHappy(self, n: int) -> bool:
       seen = []
       while n != 1:
           n = sum(int(i) ** 2 for i in str(n))
           if n in seen:
               return False
           seen.append(n)
       return True

LeetCode 1 两数之和

题目描述

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

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

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

思路

  1. 方法一:for循环暴力法
  2. 方法二:
    • 新建一个字典,用于记录已经遍历过的数组元素的值、原下标
    • 遍历数组,计算目标值与当前值的差值。若该差值在字典里,则完成检索;若字典里无该差值,则将当前值存入字典

代码

class Solution(object):
    def twoSum(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """
        record = {}
        for i in range(len(nums)):
            if target - nums[i] in record:
                return [record[target - nums[i]], i]
            else:
                record[nums[i]] = i
class Solution(object):
    def twoSum(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """
        records = dict()
        for index, value in enumerate(nums):  
            if target - value in records:   
                return [records[target- value], index]
            records[value] = index    
        return []

总结

很多时候看到题目的第一眼还是会最先冒出暴力法,可能是算法还不够熟练,还得多看看别人高效的方法。

附:本节代码随想录讲解链接

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值