18. 4Sum (通用算法 nSum)
Given an array S of n integers, are there elements a, b, c, and d in S such that a + b + c + d = target? Find all unique quadruplets in the array which gives the sum of target.
Note:
Elements in a quadruplet (a,b,c,d) must be in non-descending order. (ie, a ≤ b ≤ c ≤ d)
The solution set must not contain duplicate quadruplets.
For example, given array S = {1 0 -1 0 -2 2}, and target = 0.
A solution set is:
(-1, 0, 0, 1)
(-2, -1, 1, 2)
(-2, 0, 0, 2)
/** * Return an array of arrays of size *returnSize. * Note: The returned array must be malloced, assume caller calls free(). */ int** fourSum(int* nums, int numsSize, int target, int* returnSize) { quickSort(nums, 0, numsSize-1); int* elem = malloc(sizeof(int)*4); int** returnArray = malloc(sizeof(int*)*1000); nSum(nums, numsSize, target, elem, returnArray, returnSize, 4); return returnArray; } void twoSum(int* nums, int numsSize, int target, int* elem, int** returnArray, int* returnSize){ int j = 0; int k = numsSize-1; while(j<k){ if(nums[j]+nums[k] < target) j++; else if(nums[j]+nums[k] > target) k--; else{ elem[2] = nums[j]; elem[3] = nums[k]; int* returnElem = malloc(sizeof(int)*4); memcpy(returnElem, elem,sizeof(int)*4); returnArray[*returnSize] = returnElem; (*returnSize)++; j++; k--; while(j<k && nums[j]==nums[j-1]) j++; //To avoid duplicate triplets while(j<k && nums[k]==nums[k+1]) k--; } } } void nSum(int* nums, int numsSize, int target, int* elem, int** returnArray, int* returnSize, int N){ if(N<=2) { twoSum(nums, numsSize, target, elem, returnArray, returnSize); return; } N--; for(int i = 0; i < numsSize-N; i++){ elem[4-N-1] = nums[i]; nSum(nums+i+1, numsSize-i-1, target-nums[i], elem, returnArray, returnSize, N); while(nums[i+1]==nums[i]) i++; //To avoid duplicate triplets } } void quickSort(int* nums, int start, int end){ int p1 = start+1; int p2 = end; int tmp; while(p1 <= p2){ while(p1 <= p2 && nums[p1] <= nums[start]){ p1++; } while(p1 <= p2 && nums[p2] > nums[start]){ p2--; } if(p1 < p2){ tmp = nums[p1]; nums[p1] = nums[p2]; nums[p2] = tmp; p1++; p2--; } } //put the sentinel at the end of the first subarray if(start!=p2){ tmp = nums[start]; nums[start] = nums[p2]; nums[p2] = tmp; } if(start < p2-1) quickSort(nums,start, p2-1); //sort first subarray (<=sentinel) if(p1 < end) quickSort(nums,p1, end); //sort second subarray (>sentinel) }