目录
题目描述:
给你一个由 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
你可以按 任意顺序 返回答案 。
示例 1:
输入:nums = [1,0,-1,0,-2,2], target = 0 输出:[[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]]
示例 2:
输入:nums = [2,2,2,2,2], target = 8 输出:[[2,2,2,2]]
提示:
1 <= nums.length <= 200
-109 <= nums[i] <= 109
-109 <= target <= 109
通过次数
511.8K
提交次数
1.4M
通过率
36.7%
题目分析:
力扣估计是和xx之和给杠上了,这个和之前的两数之和,三数之和是一个思路,都是用双指针法。三数之和:https://mp.csdn.net/mp_blog/creation/editor/133312362
只不过区别在于,在对数组排序好后,两数之和是直接用双指针,三数之和是固定好第一个数后用双指针,而本题四数之和是固定号前两个数后再用双指针。
需要注意的点是,题目中给的函数格式是
/**
* Return an array of arrays of size *returnSize.
* The sizes of the arrays are returned as *returnColumnSizes array.
* Note: Both returned array and *columnSizes array must be malloced, assume caller calls free().
*/
int** fourSum(int* nums, int numsSize, int target, int* returnSize, int** returnColumnSizes){
}
给定的整数都是int类型,而-10^9 <= nums[i] <= 10^9,在这个范围内的四个数相加可能会超过int类型,所以在代码中要将四个数的和强制转化成long类型。
代码:
int cmp(const void *pa,const void* pb)
{
int a=*(int *)pa;
int b=*(int *)pb;
return a>b?1:-1;
}
int** fourSum(int* nums, int numsSize, int target, int* returnSize, int** returnColumnSizes){
qsort(nums,numsSize,sizeof(int),cmp);
*returnSize=0;
int base=100;
//先申请一些空间
int **ret=(int **)malloc(sizeof(int *)*base);
*returnColumnSizes=(int *)malloc(sizeof(int)*base);
int i,j,k,l;
for(i=0;i<numsSize-3;i++)
{
//去重
if(i>0&&nums[i]==nums[i-1])
continue;
//确定第一个数后的最小的数都比目标值大,则,不会有四数之和==target了
if((long)nums[i]+nums[i+1]+nums[i+2]+nums[i+3]>target)
break;
//确定第一个数后的最大的四数和都比target小,则这一趟找不到和为target的四个数了
if((long)nums[i]+nums[numsSize-3]+nums[numsSize-2]+nums[numsSize-1]<target)
continue;
for(j=i+1;j<numsSize-2;j++)
{
//去重
if(j>i+1&&nums[j]==nums[j-1]) continue;//这里不能写while,要写if
//和外面那次循环的优化思路一样
if ((long) nums[i] + nums[j] + nums[j + 1] + nums[j + 2] > target) {
break;
}
if ((long) nums[i] + nums[j] + nums[numsSize - 2] + nums[numsSize - 1] < target) {
continue;
}
k=j+1;
l=numsSize-1;
while(k<l)
{
long long sum=(long) nums[i]+nums[j]+nums[k]+nums[l];//=右边的也要强制转换
if(sum==target)
{
//申请一个四元组的空间
ret[*returnSize]=(int *)malloc(sizeof(int)*4);
//赋值
(*returnColumnSizes)[*returnSize]=4;
ret[*returnSize][0]=nums[i];
ret[*returnSize][1]=nums[j];
ret[*returnSize][2]=nums[k];
ret[*returnSize][3]=nums[l];
(*returnSize)++;
//空间不够时,realloc重新申请
if((*returnSize)==base)
{
base*=2;
ret=(int **)realloc(ret,sizeof(int *)*base);
*returnColumnSizes=(int *)realloc(*returnColumnSizes,sizeof(int)*base);
}
//去重
int num1=nums[k],num2=nums[l];
while(nums[k]==num1&&k<l) k++;
while(nums[l]==num2&&k<l) l--;
}
else if(sum>target) l--;
else k++;
}
}
}
return ret;
}
补充:
在确定第一个数和第二个数的时候,可以对一些特殊情况进行补充,可以提升运行速度。在上面的代码中以及写出来了。