代码随想录算法训练营第六天 | 242.有效的字母异位词 349. 两个数组的交集 202. 快乐数 1. 两数之和

哈希表基础知识

https://programmercarl.com/%E5%93%88%E5%B8%8C%E8%A1%A8%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.html
需要快速判断一个元素是否出现在集合里的时候就要考虑使用哈希法
哈希表牺牲了空间换取时间,因为要使用额外数组、set或map来存放数据,才能实现快速查找

  • 根据关键码的值而直接进行访问的数据结构
  • 数组就是一张哈希表
  • 数组的下标 = 哈希表的关键码

哈希函数

通过hashcode把名字转化为数值:hashfunction = hashcode(name) % table size 【一行hashcode(name)数值大于hash table大小,对tablesize取模 % table size 】
index = hashfunction(name)

哈希碰撞

hashcode将两个数据映射到同一个索引上,例如出现于当名字个数大于hash table size
解决方法:

  1. 拉链法:发生冲突的元素被存在链表中,可以通过hash table的索引找到
  2. 线性探测法:必要条件事table size > data size,通过hash tabel中的空位解决碰撞问题

常见哈希结构

  1. 数组
  2. 集合(set)
  3. 映射(map)

242.有效的字母异位词

初步想法

时间紧张,并没有做过哈希表的题,直接进入题解

题解

https://programmercarl.com/0242.%E6%9C%89%E6%95%88%E7%9A%84%E5%AD%97%E6%AF%8D%E5%BC%82%E4%BD%8D%E8%AF%8D.html
a-z对应0-25
定义数组hash长度26,遍历第一个数组记录每个字母出现的频率,再遍历第二个字符串

hash = [0]*26 # 初始化为0
for i in range(0,len(s)):
	hash[s[i]-'a'] += 1 # 编译器会自动用字母的ASCII做计算
for j in range(0,len(t)):
	has[t[i] - 'a'] -= 1
for i in range(0,26):
	if hash[i] != 0:
		return False
return True

代码:

class Solution:
    def isAnagram(self, s: str, t: str) -> bool:
        hash = [0]*26 # 初始化为0
        for i in range(0,len(s)):
            hash[ord(s[i])-ord('a')] += 1 # 编译器会自动用字母的ASCII做计算
        for j in range(0,len(t)):
            hash[ord(t[j]) - ord('a')] -= 1
        for i in range(0,26):
            if hash[i] != 0:
                return False
        return True

总结

  • 数据量小用数组
  • 数据量大用set
  • 有key-value pair 用map

349. 两个数组的交集

初步想法

class Solution:
def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
return list(set(nums1) & set(nums2))

题解

https://programmercarl.com/0349.%E4%B8%A4%E4%B8%AA%E6%95%B0%E7%BB%84%E7%9A%84%E4%BA%A4%E9%9B%86.html

  1. set: 将num1转成哈希表,遍历num2中的值是否在哈希表中出现过
  2. 数组:
class Solution:
    def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
        count1 = [0]*1001
        count2 = [0]*1001
        result = []
        for i in range(len(nums1)):
            count1[nums1[i]]+=1
        for j in range(len(nums2)):
            count2[nums2[j]]+=1
        for k in range(1001):
            if count1[k]*count2[k]>0:
                result.append(k)
        return result

202. 快乐数

初步想法

题不难,新建一个set记录每次算完平方和都是什么数,当数字重复出现的时候说明进入循环,也就不可能是快乐数,这是return False的唯一情况
每一次先检查平方和是否等于一,等于返回True,不能与判断是否要返回False,不反悔则将新的放平和加入已有的平方和的set里

class Solution:
    def isHappy(self, n: int) -> bool:
        total = set()
        total.add(n)
        while 1:
            num = [int(i) for i in str(n)]
            n = sum([i**2 for i in num])
            if n == 1:
                return True
            elif n in total:
                return False
            else:
                total.add(n)

题解

https://programmercarl.com/0202.%E5%BF%AB%E4%B9%90%E6%95%B0.html
跟自己的思路是一样滴

1. 两数之和

初步想法

这题的index 和value可以是map-value pair,所以想用map解决

class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        index = 0
        hash = {}
        for i in range(len(nums)):
            hash[nums[i]] = i
        print(hash)
        while index <= len(nums):
            current = nums[index]
            need = target - current
            try:
                if index != hash[need]:
                    return index, hash[need]
                else:
                    index += 1
            except:
                index += 1

题解

https://programmercarl.com/0001.%E4%B8%A4%E6%95%B0%E4%B9%8B%E5%92%8C.html

class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        records = dict()
        for index, value in enumerate(nums):  
            if target - value in records:   # 遍历当前元素,并在map中寻找是否有匹配的key
                return [records[target- value], index]
            records[value] = index    # 如果没找到匹配对,就把访问过的元素和下标加入到map中
        return []
  • 18
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值