454.四数相加II
题目链接
力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
视频讲解
学透哈希表,map使用有技巧!LeetCode:454.四数相加II_哔哩哔哩_bilibili
笔记
- 分别遍历前两个数组和后两个数组,用时间复杂度O(n**2)解决
- 先遍历前两个数组,把其中两两相加的和以及其出现的次数存到字典里
- 再遍历后两个数组的和,检查0减去对应的和的数值是否出现在字典里,如果有,说明满足条件,那么元组的次数为字典中和对应的次数
Python代码
class Solution:
def fourSumCount(self, nums1: List[int], nums2: List[int], nums3: List[int], nums4: List[int]) -> int:
from collections import defaultdict
res = 0
dict1 = defaultdict(int)
for i in range(len(nums1)):
for j in range(len(nums2)):
dict1[nums1[i] + nums2[j]] += 1
for k in range(len(nums3)):
for l in range(len(nums4)):
if 0 - (nums3[k] + nums4[l]) in dict1:
res += dict1[0 - (nums3[k] + nums4[l])]
return res
383. 赎金信
题目链接
力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
文章讲解
笔记
- 判断magzine能不能构成ransomNote,ransomNote有的字符,magzine都必须有,且数量只能多不能少
- 把magzine中出现的字符及对应次数都存到字典defaultdict中
- 遍历ransomNote,对应字符在字典中的次数减一,如果次数小于0,说明magzine中没出现该字符或者出现的次数不够,返回False;能成功遍历完ransomNote说明满足条件,返回True
Python代码
#用字典
class Solution:
def canConstruct(self, ransomNote: str, magazine: str) -> bool:
from collections import defaultdict
dictsmall = defaultdict(int)
for i in magazine:
dictsmall[i] += 1
for j in ransomNote:
dictsmall[j] -= 1
if dictsmall[j] < 0:
return False
return True
15. 三数之和
题目链接
力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
视频讲解
梦破碎的地方!| LeetCode:15.三数之和_哔哩哔哩_bilibili
笔记
- 先对列表排序,再用双指针
- 如果排序后遇到的第一个元素就大于0,不用看后面的数了
- 要对遍历的值以及双指针指向的值做去重操作
Python代码
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
ans = []
nums.sort() #先对列表排序,再用双指针
for i in range(len(nums)-2):
if nums[i] > 0: # 排序后的第一个元素就大于0,不用看后面更大的数了
return ans
elif i > 0 and nums[i-1] == nums[i]: # 当前值和上一个值相等,去重
continue
else:
left = i + 1
right = len(nums)-1
while left < right:
if nums[i] + nums[left] + nums[right] > 0: # 右指针左移
right -= 1
elif nums[i] + nums[left] + nums[right] < 0: # 左指针右移
left += 1
else: # nums[i] + nums[left] + nums[right] = 0
ans.append([nums[i], 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 # 出了while循环说明要么不满足left < right,要么遇到的值不再重复了,可以将指针移动了
right -= 1
return ans
18. 四数之和
题目链接
力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
视频讲解
难在去重和剪枝!| LeetCode:18. 四数之和_哔哩哔哩_bilibili
笔记
- 用两层for循环加双指针的思路实现0(n**2)复杂度的算法
- 对第一层循环变量i要进行剪枝和去重的操作,剪枝判断时注意要在target大于0的情况下,因为负数加负数是会越加越小的
- 对第二层循环变量的剪枝和去重操作同上
- 其余双指针思路和三数之和相同
Python代码
class Solution:
def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
ans = []
nums.sort() # 原地排序
for i in range(len(nums)-3):
if target > 0 and nums[i] > target: # target是正数的情况下,剪枝
return ans
if i > 0 and nums[i] == nums[i-1]: # 去重
continue
for j in range(i+1,len(nums)-2):
if target > 0 and nums[i] + nums[j] > target: # 剪枝
break
if j > i+1 and nums[j] == nums[j-1]: # 去重
continue
left = j + 1
right = len(nums) - 1
while left < right:
s = nums[i] + nums[j] + nums[left] + nums[right]
if s < target:
left += 1
elif s > target:
right -= 1
else:
ans.append([nums[i], nums[j], nums[left], nums[right]])
while left < right and nums[left + 1] == nums[left]:
left += 1 # 左指针去重
while left < right and nums[right - 1] == nums[right]:
right -= 1
left += 1 # 右指针去重
right -= 1
return ans