目录
今日任务:
- 哈希表理论基础
- 242.有效的字母异位词
- 349.两个数组的交集
- 202.快乐数
- 1.两数之和
哈希表理论基础
哈希表理论:
哈希表(散列表,Hash table):
- 直白来讲,其实数组就是一张哈希表
- 通过拿空间换时间
- 哈希表中关键码就是数组下标,通过下标直接访问数组的元素
- 一般哈希表都是用来判断一个元素是否出现在集合中
例如:查询一个名字是否在这个学校
复杂度:如果使用枚举法为O(n),哈希表为O(1)
思路:将这所学校里学生的名字都存在哈希表中,查询时通过索引直接就可以知道这个名字是否在这个学校中,将学生名字映射到哈希表上就涉及到了hash function
哈希函数(hash function):
- hash function通过hashCode把名字转化为数值,一般hashCode是通过特定编码的方式,可以将其他数据格式转化为不同的数值,这样就可以把学生名字映射为哈希表上的索引数字了
哈希碰撞:
- 小王与小李都映射到索引下标为1的位置上,这一现象称为哈希碰撞
- 解决方式:拉链法、线性探测法
拉链法:
刚刚小李和小王在索引1的位置发生了冲突,发生冲突的元素都被存储在链表中。 这样我们就可以通过索引找到小李和小王了
其实拉链法就是要选择适当的哈希表的大小,这样既不会因为数组空值而浪费大量内存,也 不会因为链表太长而在查找上浪费太多时间。
线性探测法:
- 使用线性探测法,一定要保证tableSize大于dataSize。 我们需要依靠哈希表中的空位来解决碰撞问题。
例如冲突的位置,放了小李,那么就向下找一个空位放置小王的信息。所以要求tableSize一定要大于dataSize ,要不然哈希表上就没有空置的位置来存放 冲突的数据了。如图所示:
常见的三种哈希结构:
- 数组
- set
- map(映射)
242.有效的字母异位词
题目链接:242. 有效的字母异位词 - 力扣(LeetCode)
分析:
- 用长度为26的数组,分别对应26个字母
- 循环s,在相应的下标上加1
- 循环t,在相应的下标上减1
- 最后循环record的数组检查是否都为0
数组
class Solution:
def isAnagram(self, s: str, t: str) -> bool:
record = [0] * 26
for i in s:
record[ord(i) - ord('a')] += 1
for j in t:
record[ord(j) - ord('a')] -= 1
for k in range(26):
if record[k] != 0:
return False
return True
default
class Solution:
def isAnagram(self, s: str, t: str) -> bool:
from collections import defaultdict
s_dict = defaultdict(int)
t_dict = defaultdict(int)
for x in s:
s_dict[x] += 1
for x in t:
t_dict[x] += 1
return s_dict == t_dict
Counter
class Solution:
def isAnagram(self, s: str, t: str) -> bool:
from collections import Counter
s_count = Counter(s)
t_count = Counter(t)
return s_count == t_count
如果不太清楚python的collections,请参考: Python——详解collections工具库 - 知乎 (zhihu.com)
349.两个数据集的交集
题目链接:349. 两个数组的交集 - 力扣(LeetCode)
分析:
- 使用set进行去重处理
- 之后循环其中一个list,看是否存在另一个list中,若存在,添加到最后的final
class Solution:
def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
nums_set1 = set(nums1)
nums_set2 = set(nums2)
final = []
for i in nums_set1:
if i in nums_set2:
final.append(i)
return final
202.快乐数
分析: 题目中说了会 无限循环,那么也就是说求和的过程中,sum会重复出现,这对解题很重要!
集合法:
class Solution:
def isHappy(self, n: int) -> bool:
n_set = set()
n_sum = n
while n_sum != 1:
if n_sum in n_set:
return False
else:
n_set.add(n_sum)
n_sum = sum(int(i) ** 2 for i in str(n_sum))
return True
暴力法:
class Solution:
def isHappy(self, n: int) -> bool:
sum = n
count = 1
while sum != 1:
n_str = str(sum)
sum = 0
for i in n_str:
sum += int(i) ** 2
count += 1
if count > 9999:
return False
if sum == 1:
return True
1.两数之和
分析:
字典:
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
record = {}
for index, value in enumerate(nums):
if target - value in record:
return [record[target - value], index]
record[value] = index
return []
暴力法:
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
for i in range(len(nums)):
for j in range(i + 1, len(nums)):
if nums[i] + nums[j] == target:
return [i, j]