题目链接:https://leetcode.com/problems/4sum/
依次将问题转化为3Sum、2Sum问题, 后两个问题解法见关联博文。
/**
* Return an array of arrays of size *returnSize.
* Note: The returned array must be malloced, assume caller calls free().
*/
void sort(int* nums, int n) { //归并算法实现排序
int pace = 1;
int lBegin, lEnd, rBegin, rEnd;
int i, j, k;
int *tmp = (int *)malloc(sizeof(int) * n);
while (pace < n) { //以pace为步长迭代归并每次迭代pace长内数据已排序,将相邻两个pace长数组进行归并
lBegin = 0;
while (lBegin + pace < n) { //剩下数字不大于pace时停止归并
lEnd = lBegin + pace - 1;
rBegin = lBegin + pace;
rEnd = lEnd + pace < n ? lEnd + pace : n - 1; //结尾不超过数组最后一个元素
i = k = lBegin, j = rBegin;
while (i <= lEnd && j <= rEnd)
if (nums[i] <= nums[j])
tmp[k++] = nums[i++];
else
tmp[k++] = nums[j++];
while (i <= lEnd)
tmp[k++] = nums[i++];
while (j <= rEnd)
tmp[k++] = nums[j++];
for (k = lBegin; k <= rEnd; ++k)
nums[k] = tmp[k];
lBegin += 2 * pace;
}
pace *= 2;
}
free(tmp);
}
int** fourSum(int* nums, int numsSize, int target, int* returnSize) {
int i, j, left, right;
int twoSum;
int** ret = (int **)malloc(1000 * sizeof(int *));
for(i = 0; i < 1000; ++i)
ret[i] = (int *)malloc(4 * sizeof(int));
sort(nums, numsSize);
*returnSize = 0;
for(i = 0; i < numsSize; ++i) {
if(i > 0 && nums[i] == nums[i - 1]) //重复数字直接跳过
continue;
for(j = i + 1; j < numsSize; ++j) {
if(j > i + 1 && nums[j] == nums[j - 1]) //重复数字直接跳过
continue;
twoSum = target - nums[i] - nums[j]; //确定前两个数后问题转换为twoSum,实现算法Log(N)时间复杂度
left = j + 1;
right = numsSize - 1;
while(left < right) {
if(nums[left] + nums[right] < twoSum)
++left;
else if(nums[left] + nums[right] > twoSum)
--right;
else { //找到和为target的四个,如果解还不存在(只需要与上一次保存的解比较)保存到输出数组
if(*returnSize == 0 || nums[i] != ret[*returnSize - 1][0] || nums[j] != ret[*returnSize - 1][1] || nums[left] != ret[*returnSize - 1][2] || nums[right] != ret[*returnSize - 1][3]) {
ret[*returnSize][0] = nums[i];
ret[*returnSize][1] = nums[j];
ret[*returnSize][2] = nums[left];
ret[*returnSize][3] = nums[right];
++*returnSize;
}
++left;
--right;
}
}
}
}
return ret;
}