2025/3/1 【双指针】LeetCode18.四数之和 【√】
终于走完双指针这一节了
方法一:双指针
具体为两个for循环(对应第一和第二个数)加left和right指针(找第三和第四个数)
class Solution: def fourSum(self, nums: List[int], target: int) -> List[List[int]]: res = [] n = len(nums) if n < 4: return res nums.sort() for i in range(n-3): if target > 0 and nums[i] > target: return res if i > 0 and nums[i] == nums[i-1]: continue for j in range(i+1, n-2): if target > 0 and nums[i] + nums[j] > target: break # return res #注意!!!:如果这里直接return会导致有的组合没法输出 #[-10, -9, -8, -8, -8, -7, -2, 0, 0, 1, 3, 5, 6, 7, 7, 8, 8],target=4 # -2和7加起来大于4,直接return了,但后面得[0,0,1,3]是一个解,被跳过了 if j > i+1 and nums[j] == nums[j-1]: continue left, right = j+1, n-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[right] == nums[right-1]: right -= 1 while left < right and nums[left] == nums[left+1]: left += 1 right -= 1 left += 1 return res
方法二:依旧是指针法。
我的方法:可以看做四个指针,分为两组的方法。
外圈的两个指针b_l,b_r,分别指代第一和第四个数字。
内圈的两个指针s_l,s_r,分别指代第二和第三个数字。
class Solution: def fourSum(self, nums: List[int], target: int) -> List[List[int]]: length = len(nums) res = [] if length < 4: return res nums.sort() res = [] for b_l in range(length-3): if target > 0 and nums[b_l] > target: return res if b_l > 0 and nums[b_l] == nums[b_l-1]: continue b_r = length-1 while b_l < b_r: s_l = b_l + 1 s_r = b_r - 1 while s_l < s_r: sum = nums[b_l] + nums[b_r] + nums[s_l] + nums[s_r] if sum > target: s_r -= 1 elif sum < target: s_l += 1 else: res.append([nums[b_l], nums[s_l], nums[s_r], nums[b_r]]) while s_r > s_l and nums[s_r] == nums[s_r-1]: s_r -= 1 while s_r > s_l and nums[s_l] == nums[s_l+1]: s_l += 1 s_r -= 1 s_l += 1 while b_r > s_l and nums[b_r] == nums[b_r-1]: b_r -= 1 b_r -= 1 return res
方法三:使用字典,元组,集合
这个解法需要对字典,元组,集合熟悉,才能灵活运用。
这个方法没有事先对nums排序。把满足条件得四个数字组合为元组形式,用集合避免重复。
class Solution: def fourSum(self, nums: List[int], target: int) -> List[List[int]]: freq = {} for num in nums: freq[num] = freq.get(num, 0) + 1 res = set() n = len(nums) for i in range(n-3): for j in range(i+1, n-2): for k in range(j+1, n-1): val = target - (nums[i] + nums[j] + nums[k]) if val in freq: count = (nums[i] == val) + (nums[j] == val) + (nums[k] == val) if count < freq[val]: res.add(tuple(sorted([nums[i], nums[j], nums[k], val]))) return [list(x) for x in res]