题目一:四数相加II
链接:
思路:首先用双循环遍历构成a+b的值和出现的次数,用字典接收,由于a+b+c+d=0,因为在对c和d进行双循环后,在字典中找到0-c-d,得出它的值也就是出现次数,进行出现次数的累计,就得到了
有多少个元组 (i, j, k, l)
能满足:
0 <= i, j, k, l < n
nums1[i] + nums2[j] + nums3[k] + nums4[l] == 0
class Solution: def fourSumCount(self, nums1: List[int], nums2: List[int], nums3: List[int], nums4: List[int]) -> int: hashmap =dict() for a in nums1: for b in nums2: hashmap[a+b]=hashmap.get(a+b,0)+1 count = 0 for c in nums3: for d in nums4: target = -c-d if target in hashmap: count+=hashmap[target] return count
题目二:赎金信
-
题目链接/文章讲解: 代码随想录
思路:通过比较赎金信的各个字母出现的次数都要小于等于杂志出现的字母个数来判定,定义数组,用26个字母的unicode次序来确定索引,每个字母出现一次,对应索引次数加1
class Solution: def canConstruct(self, ransomNote: str, magazine: str) -> bool: ransomNote_count = [0]*26 magazine_count = [0]*26 for i in ransomNote: ransomNote_count[ord(i)-ord('a')]+=1 for i in magazine: magazine_count[ord(i)-ord('a')]+=1 return all(ransomNote_count[a]<=magazine_count[a] for a in range(26))
题目三:三数之和
思路:
使用双指针的方法,每遍历一次数组,都是先让左边第一个数作为i,固定,让left往右移动,right往左移动进行遍历,如果sum>0,则让right往左移动,如果sum<0,则让left往右移动;注意点是i和left以及right的去重,
i的去重:检查第i项以及第i-1项是否相等,如果相等,就跳过
left 和right的去重:等到往结果result中加入一个元组之后,在考虑去重,只要当前right和往左移动后的下一个right数组对应的值相等,就right减一,left同理
class Solution: def threeSum(self, nums: List[int]) -> List[List[int]]: result = [] nums.sort() for i in range(len(nums)): 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: 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]]) 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 result
题目四:四数之和
思路:跟三数之和,相比,一是多了一层循环,多了一次去重;二是由于target不确定是否是大于零还是小于零,因此需要进行一级剪枝操作,也就是如果nums[k]大于零,且target大于零,且nums[k]>0,那么就跳出循环;二级剪枝操作,判断nums[k]+nums[i]>target 且target大于零,是的话就跳出循环
class Solution: def fourSum(self, nums: List[int], target: int) -> List[List[int]]: result =[] nums.sort() n = len(nums) for k in range(n): if(nums[k]>target and target >0 and nums[k]>0): break if(k>0 and nums[k]==nums[k-1]): continue for i in range(k+1,n): if(nums[k]+nums[i]>target and target >0): break if(i>k+1 and nums[i]==nums[i-1]): continue left = i+1 right = n-1 while left < right: sum_ = nums[k]+nums[i]+nums[left]+nums[right] if sum_ > target: right -=1 elif sum_ < target: left +=1 else: result.append([nums[k],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 right -=1 return result