- 三数之和;给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组
- 四数之和;给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] (若两个四元组元素一一对应,则认为两个四元组重复)
题目特点:这两题有一个特点就是三元组(四元组)不能重复
解决方法:双指针
三数之和:
- 首先对nums进行排序(这里按照升序排序),并计算nums长度,记为nums_l
- 将nums[i]作为为三元组的第一个数
- 左指针left存放索引(i+1),右指针right存放索引(nums_l - 1),将nums[left] 于 nums[right]作为三元组第二个数与第三个数。
- 判断nums[i] + nums[left] + nums[right] 是否等于目标值(target,在三数之和中,target值为0),若值小于目标值,则 left += 1,若值大于目标值,则right -= 1,若为0,则存入列表(res)并将left向右移,直到 left 指向的值不同于之前的值,同理,right 向左移动,直到 right 指向的值不同于之前的值。在移动的过程中需要满足 left < right,若满足则继续移动,若不满足则跳出指针移动循环。
- 回到2,从索引 i 开始,往右寻找第一个不等于nums[i]的数,作为三元组的第一个数,重复3、4、5操作
nums_l = len(nums)
nums.sort(reverse=False)
res = []
for i in range(nums_l):
if i >= 1 and nums[i] == nums[i-1]:
continue
left = i + 1
right = nums_l - 1
while left < right:
total = nums[i] + nums[left] + nums[right]
if total < 0:
left += 1
elif total > 0:
right -= 1
else:
res.append([nums[i], nums[left], nums[right]])
while left != right and nums[left] == nums[left+1]:
left += 1
while left != right and nums[right-1] == nums[right]:
right -= 1
left += 1
right -= 1
return res
四数之和:
整体思路于三数之和类似,差别在于要多加一层循环,在三数之和中事先确定一个数,在四数之和中需要确定两个数。
- 首先对nums进行排序(这里按照升序排序),并计算nums长度,记为nums_l
- 确定nums[i]确认为四元组的第一个数,确定nums[j] = nums[i+1]为四元组的第二个数
- 左指针left存放索引(j+1),右指针right存放索引(nums_l - 1)
- 判断nums[i] + nums[j] + nums[left] + nums[right] 是否等于目标值,left和right的操作于三数之和相同
- 在nums中,从 j 开始,寻找第一个不等于nums[j]的数,四元组的第二个数,并重复3、4、5,当 j 到达nums的末尾时,则跳回到步骤2。
nums.sort()
nums_l = len(nums)
res = []
for i in range(nums_l):
if i > 0 and nums[i] == nums[i - 1]:
continue
for j in range(i + 1, nums_l):
if j > i + 1 and nums[j] == nums[j - 1]:
continue
left = j + 1
right = nums_l - 1
while left < right:
total = nums[i] + nums[left] + nums[right] + nums[j]
if total < target:
left += 1
elif total > target:
right -= 1
elif total == target:
res.append([nums[i], nums[left], nums[right], nums[j]])
while left < right and nums[left] == nums[left+1]: left += 1
while left < right and nums[right-1] == nums[right]: right -= 1
left += 1
right -= 1
return res
参考:
三数之和来源:力扣(LeetCode) 链接:力扣
四数之和来源:力扣(LeetCode) 链接:力扣