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)
}
原文地址:https://www.cnblogs.com/qionglouyuyu/p/5400678.html