题意:
给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] (若两个四元组元素一一对应,则认为两个四元组重复):
0 <= a, b, c, d < n a、b、c 和 d 互不相同 nums[a] + nums[b] + nums[c] + nums[d] == target 你可以按 任意顺序 返回答案 。
思路:
- 整体思路和三数之和差不多,就是多了一层循环嵌套,固定两个数,再来用双指针移动
- 要多注意的点还是去重的问题 ,在这里多写一些判断的条件,可以更快速的进行查找
/**
* @param {number[]} nums
* @param {number} target
* @return {number[][]}
*/
var fourSum = function(nums, target) {
//定义一个接收结果的数组
let result = []
//若传入的数组的个数不够4个,则无法返回满足条件的四元组。
if (nums.length<4){
return result
}
//为传入的数组进行排序,即算去重
nums.sort((a,b)=>a-b)
//两层循环嵌套,固定四元组的两个数字
let length= nums.length
//第一层循环:
for(let i =0;i<length-3;i++){
//若当前数与上一个数相同,则跳过当前的数,往后遍历
if(i>0 && nums[i]===nums[i-1]){
continue
}
//若数组的前四个数字的和已经>target值了,则跳出循环
if(nums[i]+nums[i+1]+nums[i+2]+nums[i+3]>target){
break
}
//若数组的第一个加后三个数字的和<target值,则说明i的值要增大了
if(nums[i]+nums[length-1]+nums[length-2]+nums[length-3]<target){
continue
}
//第二层循环:
for(let j=i+1;j<length-2;j++){
//若当前数与上一个数相同,则跳过当前的数,往后遍历
if(j>i+1 && nums[j]===nums[j-1]){
continue
}
//若数组的前四个数字的和已经>target值了,则跳出循环
if(nums[i]+nums[j]+nums[j+1]+nums[j+2]>target){
break
}
//若数组的第一个加后三个数字的和<target值,则说明j的值要增大了
if(nums[i]+nums[j]+nums[length-1]+nums[length-2]<target){
continue
}
//需要两个不断挪动的指针,计算它们四个的和,并与target进行比较。
let start = j+1,end = length-1
while(start<end){
//若四个数之和===target,则判断start,end的值是否与它们的上一个数相等,相等则跳过
if(nums[i]+nums[j]+nums[start]+nums[end]===target){
result.push([nums[i],nums[j],nums[start],nums[end]])
while(start<end && nums[start]===nums[start+1]){
start++
}
start++
while(start<end && nums[end]===nums[end-1]){
end--
}
end--
}
else if(nums[i]+nums[j]+nums[start]+nums[end]<target){
start++
}
//若四个数之和>target,则说明要减小它们的和,即要end--
else{
end--
}
}
}
}
return result
//返回最终结果
};