Okii's blog

仅作为记录自己的学习过程

0%

Leetcode 哈希表篇

Leetcode刷题记录——哈希表篇

Leetcode242 有效的字母异位词

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

Python代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Solution:
def isAnagram(self, s: str, t: str) -> bool:
# 首先定义一个record数组, 初始化全为0
record = [0] * 26
# 遍历s字符串, 因为都是小写字母, 所以用相对位置即可
# 对于s字符串, 出现的字母下标位置+1
for i in s:
record[ord(i) - ord("a")] += 1
# 对于t字符串, 出现的字母下标位置-1
for i in t:
record[ord(i) - ord("a")] -= 1
# 如果, t是s的字母异位词, 那么record数组1的地方应该刚好被抵消, 全为0
# 否则t不是s的字母异位词
for i in record:
if i != 0:
return False
return True

Leetcode349 两个数组的交集

Python代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
class Solution:
def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
count1 = [0] * 1000
count2 = [0] * 1000
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(len(count1)):
if count1[i] * count2[i] > 0:
res.append(i)
return res

Leetcode202 快乐数

题目中说了会 无限循环,那么也就是说求和的过程中,sum会重复出现,这对解题很重要

当我们遇到了要快速判断一个元素是否出现集合里的时候,就要考虑哈希法了。

所以这道题目使用哈希法,来判断这个sum是否重复出现,如果重复了就是return False, 否则一直找到sum为1为止。

Python代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
class Solution:
def isHappy(self, n: int) -> bool:
res = set()
while n != 1:
sum = 0
for i in str(n):
sum += int(i) ** 2
if sum in res:
return False
res.add(sum)
n = sum
return True

Leetcode1 两数之和

简单的方式是直接两层for循环遍历所有可能的情况,但复杂度是O(n^2)

map,也就是字典来解题

首先遍历nums,判断target - value是否出现在字典,若字典里有,则返回相应的下标

若没有,则将value-index这对键值对加入字典

Python代码如下:

1
2
3
4
5
6
7
8
9
10
11
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
map = {}
res = []
for index, value in enumerate(nums):
if target - value in map:
res.append(index)
res.append(map[target-value])
if value not in map:
map[value] = index
return res

Leetcode383 赎金信

题目中说:magazine 中的每个字符只能在 ransomNote 中使用一次

那么就考虑哈希表的思路去做

首先遍历magazine ,将其中的字符以及个数添加到map

再遍历ransomNote,如果其中字符存在map中,且map[i] > 0,则对应 -1,否则返回False

若循环顺利结束,说明条件成立,返回True

Python代码如下:

1
2
3
4
5
6
7
8
9
10
11
class Solution:
def canConstruct(self, ransomNote: str, magazine: str) -> bool:
map = {}
for i in magazine:
map[i] = map.get(i, 0) + 1
for i in ransomNote:
if i in map and map[i] > 0:
map[i] -= 1
else:
return False
return True

Leetcode454 四数相加II

首先定义一个mapkeya+b的值,value是其出现的次数

再遍历c+d,若相加=0,则count加上对应的value

Python代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
class Solution:
def fourSumCount(self, nums1: List[int], nums2: List[int], nums3: List[int], nums4: List[int]) -> int:
map = {}
count = 0
for a in nums1:
for b in nums2:
map[a+b] = map.get(a+b, 0) + 1
for c in nums3:
for d in nums4:
if -(c+d) in map and map[-(c+d)] > 0:
count += map[-(c+d)]
return count

Leetcode15 三数之和

首先将数组排序,然后有一层for循环,i从下标0的地方开始

同时定一个下标left 定义在i+1的位置上,定义下标right在数组结尾的位置上。

依然还是在数组中找到 abc 使得a + b +c =0

我们这里相当于 a = nums[i]b = nums[left]c = nums[right]

接下来如何移动leftright呢, 如果nums[i] + nums[left] + nums[right] > 0 就说明 此时三数之和大了,因为数组是排序后了,所以right下标就应该向左移动,这样才能让三数之和小一些。

如果 nums[i] + nums[left] + nums[right] < 0 说明此时三数之和小了,left 就向右移动,才能让三数之和大一些,直到leftright相遇为止。

Python代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
res = []
nums.sort()
for i in range(len(nums)):
# 因为是排序后的, 如果nums[i], 那就没必要继续了
if nums[i] > 0:
return res
# 每次i往后一位时,需要判断与之前是否相同,因为会重复
# 看参考样例[-1,0,1,2,-1,-4]
if i> 0 and nums[i] == nums[i-1]:
continue
left = i + 1
right = len(nums) - 1
while left < right:
sum = nums[i] + nums[left] + nums[right]
if sum > 0:
right -= 1
elif sum < 0:
left += 1
else:
res.append([nums[i], nums[left], nums[right]])
# 当前位置匹配成功过,跳过相同元素避免重复
while left < right and nums[right] == nums[right-1]:
right -= 1
while left < right and nums[left] == nums[left+1]:
left += 1
right -= 1
left += 1
return res

Leetcode18 四数之和

四数之和的双指针解法是两层for循环nums[i] + nums[j]为确定值,依然是循环内有leftright下标作为双指针,找出nums[i] + nums[j] + nums[left] + nums[right] == target的情况,三数之和的时间复杂度是O(n^2),四数之和的时间复杂度是O(n^3)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Solution:
def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
nums.sort()
res = []
for i in range(len(nums)):
if i > 0 and nums[i] == nums[i-1]:
continue
for j in range(i+1, len(nums)):
if j > i+1 and nums[j] == nums[j-1]:
continue
left = j + 1
right = len(nums) - 1
while left < right:
sum = nums[i] + nums[j] + nums[left] + nums[right]
if sum > target:
right -= 1
elif sum < target:
left += 1
else:
res.append([nums[i], nums[j], nums[left], nums[right]])
while left < right and nums[left] == nums[left+1]:
left += 1
while left < right and nums[right] == nums[right-1]:
right -= 1
left += 1
right -= 1
return res