系列文章
python coding with ChatGPT 打卡第1天| 二分查找、移除元素
python coding with ChatGPT 打卡第2天| 双指针、滑动窗口、螺旋矩阵
python coding with ChatGPT 打卡第3天| 移除链表、设计链表、反转链表
python coding with ChatGPT 打卡第4天| 链表其他操作:两两交换、删除倒数第N个节点 链表相交 环形链表
python coding with ChatGPT 打卡第5天| 哈希表:有效字母异位词、两个数组的交集、快乐数、两数之和
454. 四数相加II
map使用技巧
def fourSumCount(nums1, nums2, nums3, nums4):
count = 0
for val1 in nums1:
for val2 in nums2:
for val3 in nums3:
for val4 in nums4:
if val1 + val2 + val3 + val4 == 0:
count += 1
return count
使用字典
def fourSumCount(nums1, nums2, nums3, nums4):
record = dict()
count = 0
for val1 in nums1:
for val2 in nums2:
val_sum1 = val1 + val2
if val_sum1 in record:
record[val_sum1] += 1
else:
record[val_sum1] = 1
for val3 in nums3:
for val4 in nums4:
val_sum2 = val3 + val4
val_target = 0 - val_sum2
if val_target in record:
count += record[val_target]
return count
更简洁的写法:
if val_sum1 in record:
record[val_sum1] += 1
else:
record[val_sum1] = 1
# 可以直接写成1行
record[val_sum1] = record.get(val_sum1, 0) + 1
383. 赎金信
方法1:字典法
def canConstruct(ransomNote, magazine):
record = dict()
for char in magazine:
record[char] = record.get(char, 0) + 1
for char in ransomNote:
if char in record:
record[char] -= 1
if record[char] < 0:
return False
else:
return False
return True
方法2:数组法
def canConstruct(ransomNote, magazine):
record = [0]*26
for char in magazine:
record[ord(char)-ord('a')] +=1
for char in ransomNote:
record[ord(char)-ord('a')] -= 1
if all(x>=0 for x in record):
return True
return False
15. 三数之和
梦破碎的地方
def threeSum(nums):
res = []
nums.sort()
for i in range(len(nums)):
if i > 0:
if nums[i] == nums[i-1]:
continue
left = i + 1
right = len(nums)-1
while left < right:
if nums[i] + nums[left] + nums[right] == 0:
res.append([nums[i], nums[left], nums[right]])
left += 1
while left < len(nums)-1 and nums[left] == nums[left-1]:
left += 1
right -= 1
while right > 0 and nums[right] == nums[right+1]:
right -= 1
elif nums[i] + nums[left] + nums[right] > 0:
right -= 1
else:
left += 1
return res
四数之和,和15.三数之和是一个思路,都是使用双指针法, 基本解法就是在15.三数之和的基础上再套一层for循环。
18. 四数之和
难在去重和剪枝
其实不做剪枝也可以通过,我的代码就没有写剪枝的内容
def fourSum(nums, target):
res = []
nums.sort()
for i in range(len(nums)):
if i > 0:
if nums[i] == nums[i-1]:
continue
for k in range(i+1,len(nums)-1):
if k > i+1:
if nums[k] == nums[k-1]:
continue
left = k + 1
right = len(nums) - 1
while left < right:
if nums[i] + nums[k] + nums[left] + nums[right] == target:
res.append([nums[i], nums[k], nums[left], nums[right]])
left += 1
right -= 1
while left < len(nums)-1 and nums[left] == nums[left-1]:
left += 1
while right > 0 and nums[right] == nums[right+1]:
right -= 1
elif nums[i] + nums[k] + nums[left] + nums[right] > target:
right -= 1
else:
left += 1
return res
一样的道理,能解决四数之和 那么五数之和、六数之和、N数之和呢?
四数之和的双指针解法是两层for循环nums[k] + nums[i]为确定值,依然是循环内有left和right下标作为双指针,找出nums[k] + nums[i] + nums[left] + nums[right] == target的情况,三数之和的时间复杂度是O(n2),四数之和的时间复杂度是O(n3) 。
因此,对于三数之和双指针法就是将原本暴力O(n3)的解法,降为O(n2)的解法,四数之和的双指针解法就是将原本暴力O(n4)的解法,降为O(n3)的解法。
那么一样的道理,五数之和、六数之和等等都采用这种解法。
之前我们讲过哈希表的经典题目:454.四数相加II相对于本题简单很多,因为本题是要求在一个集合中找出四个数相加等于target,同时四元组不能重复。而454.四数相加II是四个独立的数组,只要找到A[i] + B[j] + C[k] + D[l] = 0就可以,不用考虑有重复的四个元素相加等于0的情况,所以相对于本题还是简单了不少!
双指针法将时间复杂度:O(n2)的解法优化为 O(n)的解法。也就是降一个数量级,题目如下:
27. 移除元素
15. 三数之和
18. 四数之和
题目详解
链表相关:
206. 反转链表
19. 删除链表的倒数第N个节点
160. 链表相交
142. 环形链表II
题目详解1
题目详解2