分析:要求四个数的和,可以转换成三个数的和
解决方案:排序+双指针
int comp(const void* a,const void* b){
return *(int*)a-*(int*)b;
}
int** fourSum(int* nums, int numsSize, int target, int* returnSize, int** returnColumnSizes){
*returnSize=0;
if(numsSize<4)
return NULL;
qsort(nums,numsSize,sizeof(int),comp);
int** ret=(int**)malloc(sizeof(int)*(numsSize+1)*6);
assert(ret);
*returnColumnSizes=(int*)malloc(sizeof(int)*(numsSize+1)*6);
assert(*returnColumnSizes);
int s1,s2,left,right;
//s1和s2只指向第一次出现的元素,若再次出现,跳过
for(s1=0;s1<numsSize-3;++s1){
//使用以下方式去重时,在计算最大值时,所得的最大值并非最大
//因为s1会跳过相同的,所以计算有误
//while(s1!=0&&(s1<numsSize-3)&&(nums[s1]==nums[s1-1]))
// s1++;
//最小值都比目标值,结束循环
if(nums[s1]+nums[s1+1]+nums[s1+2]+nums[s1+3]>target)
break;
//s1此时指向的元素,加上s1之后的最大的三个元素小于目标值
//结束当轮循环,s1指向下一个元素
if(nums[s1]+nums[numsSize-1]+nums[numsSize-2]+nums[numsSize-3]<target)
continue;
if (s1 > 0 && (nums[s1] == nums[s1 - 1]))
continue;
for(s2=s1+1;s2<numsSize-2;++s2){
while(s2!=s1+1&&(s2<numsSize-2)&&(nums[s2]==nums[s2-1]))
s2++;
left=s2+1,right=numsSize-1;
while(left<right){
int sum=nums[s1]+nums[s2]+nums[left]+nums[right];
if(sum<target)
++left;
else if(sum>target)
--right;
else{
ret[(*returnSize)]=(int*)malloc(sizeof(int)*4);
returnColumnSizes[0][(*returnSize)]=4;
ret[*returnSize][0]=nums[s1];
ret[*returnSize][1]=nums[s2];
ret[*returnSize][2]=nums[left++];
ret[*returnSize][3]=nums[right--];
(*returnSize)++;
while(left<right&&nums[left]==nums[left-1])
++left;
while(left<right&&nums[right]==nums[right+1])
--right;
}
}
}
}
return ret;
}