声明:
今天是中等题第11道题。给定一个包含 n 个整数的数组 nums
和一个目标值 target
,判断 nums
中是否存在四个元素 a,b,c 和 d ,使得 a + b + c + d 的值与 target
相等?找出所有满足条件且不重复的四元组。以下所有代码经过楼主验证都能在LeetCode上执行成功,代码也是借鉴别人的,在文末会附上参考的博客链接,如果侵犯了博主的相关权益,请联系我删除
(手动比心ღ( ´・ᴗ・` ))
正文
题目:给定一个包含 n 个整数的数组 nums
和一个目标值 target
,判断 nums
中是否存在四个元素 a,b,c 和 d ,使得 a + b + c + d 的值与 target
相等?找出所有满足条件且不重复的四元组。
注意:
答案中不可以包含重复的四元组。
示例:
给定数组 nums = [1, 0, -1, 0, -2, 2],和 target = 0。 满足要求的四元组集合为: [ [-1, 0, 0, 1], [-2, -1, 1, 2], [-2, 0, 0, 2] ]
解法1。和3数之和的思路很像,就是固定前2个作为i、j遍历,后两个作为p、q双指针逐渐向中间靠拢,以后遇到K数之和的问题都可以套用此范式,前K-2个用K-2个for循环遍历,后面2个用双指针,其中可以做适当剪枝,就是比如说最大和都比target小或者下一个元素值和当前的相等,那么continue,如果最小和大于target直接break,代码如下
执行用时: 104 ms, 在4Sum的Python3提交中击败了98.81% 的用户
class Solution:
def fourSum(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[List[int]]
"""
res = []
n = len(nums)
nums.sort() # 这一步千万别漏了
for i in range(n-3):
if i>0 and nums[i]==nums[i-1]:continue
if nums[i]+nums[n-1]+nums[n-2]+nums[n-3] < target:continue # 最大和都比target小,那么只有增加i,也就是跳过此次循环
if nums[i]+nums[i+1]+nums[i+2]+nums[i+3] > target:break # 最小和都比target大,直接break
for j in range(i+1,n-2):
if j>0 and nums[j] == nums[j-1]:continue
if nums[i]+nums[j]+nums[n-1]+nums[n-2]<target:continue
if nums[i]+nums[j]+nums[j+1]+nums[j+2]>target:break
l,r = j+1,n-1
tar = target - nums[i] -nums[j]
while l < r:
if nums[l]+nums[r] == tar:
res.append([nums[i],nums[j],nusm[l],nums[r]])
l += 1
r -= 1
while l < r and nums[l] == nums[l-1]:l += 1
while l < r and nums[r] == nums[r+1]:r -= 1
elif nums[l]+nums[r] > tar:
r -= 1
else:
l += 1
return res
解法2。采用递归的方式做,讲真没有细推,其实并不是很理解,代码如下。
执行用时: 112 ms, 在4Sum的Python3提交中击败了97.25% 的用户
class Solution:
def fourSum(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[List[int]]
"""
def findNsum(nums, target, N):
"""
多个数之和这一类问题的通解
:param nums:
:param target:
:param N:
:return:
:notes:
1. 传进来的nums已经完成了从小到大的排序
"""
res = []
# early termination
if len(nums) < N or target < nums[0] * N or target > nums[-1] * N:
return res
# two pointer solve sorted 2-sum problem
if N == 2:
l, r = 0, len(nums) - 1
while l < r:
s = nums[l] + nums[r]
if s < target:
l += 1
elif s > target:
r -= 1
else:
res.append([nums[l], nums[r]])
while l < r and nums[l] == nums[l + 1]:
l += 1
while l < r and nums[r] == nums[r - 1]:
r -= 1
l, r = l + 1, r - 1
else:
for i, x in enumerate(nums[: -N + 1]):
if i == 0 or (i > 0 and nums[i - 1] != x):
res1 = findNsum(nums[i + 1: ], target - x, N - 1)
if len(res1) > 0:
res += [[x] + y for y in res1]
return res
return findNsum(sorted(nums), target, 4)
结尾
解法1:https://blog.csdn.net/Koala_Tree/article/details/80104382
解法2:LeetCode