知识准备
- 哈希表:用来快速判断一个元素是否出现在集合里,数组就是一张哈希表。
- 哈希函数:存储位置(索引)与元素之间存在一个对应关系f,使每个元素key对应一个索引f(key),关系f称为哈希函数,index = f(key)。
- 哈希碰撞:两个不同的元素拥有同一个索引。解决办法:
- 链地址法:把发生索引位置冲突的元素储存在链表中,通过该索引找到链表。
- 线性探测法:寻找下一个空的地址。要求哈希表大小大于数据量的大小。
LeetCode 242 有效的字母异位词
题目描述:
给定两个字符串
s
和t
,编写一个函数来判断t
是否是s
的字母异位词。**注意:**若
s
和t
中每个字符出现的次数都相同,则称s
和t
互为字母异位词。输入: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 两个数组的交集
题目描述:
给定两个数组
nums1
和nums2
,返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。输入:nums1 = [1,2,2,1], nums2 = [2,2] 输出:[2]
思路
-
方法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:
- 用两个数组(哈希表)记录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] 。
思路
- 方法一:for循环暴力法
- 方法二:
- 新建一个字典,用于记录已经遍历过的数组元素的值、原下标
- 遍历数组,计算目标值与当前值的差值。若该差值在字典里,则完成检索;若字典里无该差值,则将当前值存入字典
代码
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 []
总结
很多时候看到题目的第一眼还是会最先冒出暴力法,可能是算法还不够熟练,还得多看看别人高效的方法。