1. 两数之和
题目链接:1. 两数之和
- 为什么使用哈希表
当需要查询元素是否出现过,或者一个元素是否在集合中时,就需要使用hash表。在本题中,针对一个元素nums[i],我们需要判断target-nums[i]是否也在其中。 - 哈希表为什么用map
不仅需要元素值,还需要储存下标 - 本题map是用来存什么的
存放已经遍历过的数值 - map中的key和value用来存什么的
key是元素值,value是下标
class Solution(object):
def twoSum(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[int]
"""
# 对于nums[i],查找target-nums[i]是否在map中
d=dict()
for i in range(len(nums)):
if target-nums[i] in d:
return [i,d[target-nums[i]]]
else:
d[nums[i]]=i
return []
时间复杂度:O(n)
空间复杂度:O(n)
454.四数相加II
题目链接:454.四数相加II
- nums1和nums2一组进行遍历,nums3和nums4一组进行遍历
- 类似于两数之和
class Solution(object):
def fourSumCount(self, nums1, nums2, nums3, nums4):
# 定义字典存放nums1和nums2之间可能的元素和
s = dict()
for i in nums1:
for j in nums2:
if i+j in s:
s[i+j] += 1
else:
s[i+j] = 1
cnt = 0
for i in nums3:
for j in nums4:
if -i-j in s:
cnt += s[-i-j]
return cnt
- 另一种计数方法:
s[n1+n2] = s.get(n1+n2, 0) + 1
时间复杂度:O(n^2)
空间复杂度:O(n^2),最坏情况下A和B的值各不相同,相加产生的数字个数为 n^2
383. 赎金信
题目链接:383. 赎金信
- 是元素是否在集合中的问题,所以想到用hash表做
class Solution(object):
def canConstruct(self, ransomNote, magazine):
s=[0]*26
for i in magazine:
s[ord(i)-ord('a')] += 1
for i in ransomNote:
s[ord(i)-ord('a')] -= 1
for i in range(26):
if s[i] < 0:
return False
return True
时间复杂度:O(n)
空间复杂度:O(1)
- 使用count
- 这里使用set是为了去除重复元素
- all(iterable)检查iterable中是否所有元素均为True,iterable可以是tuple或者list
return all(ransomNote.count(c) <= magazine.count(c) for c in set(ransomNote))
- 使用Counter,是dict字典的子类,key为待计数的元素,value为元素出现的次数
return not Counter(ransomNote) - Counter(magazine)
- 使用defaultdict:便于处理缺失key的情况。在访问或修改不存在的键时,defaultdict 会自动创建该键并为其生成一个默认值。
hashmap = defaultdict(int)
15. 三数之和
题目链接:15. 三数之和
- 题目要求不能有重复的三元组,如果使用hash,会有复杂的去重操作,因为hash是没有顺序的
- 使用双指针更合适
- 双指针前提:排序(该题并不要求返回下标,所以可以排序)
- 关键:去重!
- 判断
nums[i]=nums[i-1]
,而不是nums[i]=nums[i+1]
->是判断集合里面有没有两个相等的元素
- 判断
class Solution(object):
def threeSum(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
result=[]
nums.sort()
for i in range(len(nums)):
# 如果排序后的第一个元素就>0,则没有满足条件的三元组
if nums[i] > 0:
return result
# 对第一个位置去重
if i > 0 and nums[i] == nums[i-1]:
continue
left = i+1
right = len(nums)-1
while left < right:
# 当left==right时,集合里只有两个元素,不符合条件
# 所以循环条件是<而不是≤
sum_=nums[i]+nums[left]+nums[right]
if sum_>0:
right-=1
elif sum_<0:
left+=1
else:
result.append([nums[i],nums[left],nums[right]])
# 对left和right位置去重
while left<right and nums[left]==nums[left+1]:
left+=1
while left<right and nums[right]==nums[right-1]:
right-=1
right-=1
left+=1
return result
时间复杂度:O(n^2)
空间复杂度:O(1)
18. 四数之和
题目链接:18. 四数之和
- 使用双指针法
class Solution(object):
def fourSum(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[List[int]]
"""
result=[]
nums.sort()
# 去重
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:
result.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 result
时间复杂度:O(n^3)
空间复杂度:O(1)