LeetCode 18. 4Sum ( C ) – Medium (雙指標法、搜尋法)

本題為 3Sum 3Sum Closest 的延伸題目,可以先看前面的題目再來看這題,會比較有連貫性。

本題題目為,給定一串數字,輸出任意4個數字相加,等於目標值的所有組合。

原文題目如下

Given an array nums of n integers, return an array of all the unique quadruplets [nums[a], nums[b], nums[c], nums[d]] such that:

0 <= a, b, c, d < n
a, b, c, and d are distinct.
nums[a] + nums[b] + nums[c] + nums[d] == target
You may return the answer in any order.

解題策略分為兩總,( 1 ) 雙指標法,( 2 )搜尋法。

( 1 ) 雙指標法為,先排序整個數字陣列,再透過兩層迴圈遍歷數字,每次透過雙指標找出符合條件的值。

( 2 ) 搜尋法為,先排序整個數字陣列,再透過三層迴圈遍歷數字,每次透過二元搜尋找到符合的值。

下面是我的程式碼

( 1 ) 雙指標法

/**
 * 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 cmp(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;            // number of return pairs
    int left,right;
    int step = 4;              // each memory alloc
    *returnColumnSizes = (int*)malloc(sizeof(int*)*step); 
    int** re = (int**)malloc(sizeof(int*)*step);
	
    qsort(nums, numsSize, sizeof(int), cmp);

    for(int i = 0; i<numsSize-3 ; i++){
        if(i!=0){                               //Jump Same num
            while(i<numsSize-3){
                if(nums[i]==nums[i-1])
                    i++;
                else
                    break;
            }
        }
        if(i<numsSize-3){
            for(int j = i+1; j<numsSize-2 ; j++ ){
                if(j!=i+1){                               //Jump Same num
                    while(j<numsSize-2){
                        if(nums[j]==nums[j-1])
                            j++;
                        else
                            break;
                    }
                }
	        if(j<numsSize-2){
		    left = j+1;
		    right = numsSize-1;
		    while(right>left){
			if((nums[i]+nums[j]+nums[left]+nums[right])==target){
			    if((*returnSize) != 0 && (*returnSize)%step == 0){
			        *returnColumnSizes = (int*)realloc(*returnColumnSizes, sizeof(int*) * ((*returnSize)+step));
			        re = (int**)realloc(re, sizeof(int*) * ((*returnSize)+step));
			    }
			    (*returnColumnSizes)[*returnSize] = 4;
			    re[*returnSize] = (int*)malloc(sizeof(int)*4);
			    re[*returnSize][0] = nums[i];
			    re[*returnSize][1] = nums[j];
			    re[*returnSize][2] = nums[left];
			    re[*returnSize][3] = nums[right];
			    (*returnSize)++;
							
			    left++;
			    while((left<numsSize) && (nums[left] == nums[left-1])){
				left++;
			    }
			    right--;
			    while((right>=0) && (nums[right] == nums[right+1])){
				right--;
			    }
	                }
			else if((nums[i]+nums[j]+nums[left]+nums[right])<target){
			    left++;
			    while((left<numsSize) && (nums[left] == nums[left-1])){
			        left++;
			    }
			}
			else{
			    right--;
			    while((right>=0) && (nums[right] == nums[right+1])){
			        right--;
			    }
		        }
	            }
	        }
            }
        }
    }
   
    return re;
    
}

( 2 ) 搜尋法

/**
 * 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().
 */

void mergeSort(int* num, int numsSize);
void sortsub(int* num, int low, int high);
void merge(int* num, int low, int middleL, int middleR, int high);
bool binarySearch(int* nums, int left, int right, int target);

int cmp(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;            // number of return pairs
    int step = 4;              // each memory alloc
    *returnColumnSizes = (int*)malloc(sizeof(int*)*step); 
    int** re = (int**)malloc(sizeof(int*)*step);

    
    qsort(nums, numsSize, sizeof(int), cmp);

	for(int i = 0; i<numsSize-3 ; i++){
        if(i!=0){                               //Jump Same num
            while(i<numsSize-3){
                if(nums[i]==nums[i-1])
                    i++;
                else
                    break;
            }
        }
        if(i<numsSize-3){
            for(int j = i+1; j<numsSize-2 ; j++ ){
                if(j!=i+1){                               //Jump Same num
                    while(j<numsSize-2){
                        if(nums[j]==nums[j-1])
                            j++;
                        else
                            break;
                    }
                }
                if(j<numsSize-2){
		    for(int k = j+1; k<numsSize-1 ; k++ ){
		        if(k!=j+1){
			    while(k<numsSize-1){
			        if(nums[k]==nums[k-1])
				    k++;
				else
				    break;
			    }
		    }
		    if(k<numsSize-1){
		        if(binarySearch(nums,k+1,numsSize-1,(target-nums[i]-nums[j]-nums[k]))){
			    if((*returnSize) != 0 && (*returnSize)%step == 0){
			        *returnColumnSizes = (int*)realloc(*returnColumnSizes, sizeof(int*) * ((*returnSize)+step));
				=re = (int**)realloc(re, sizeof(int*) * ((*returnSize)+step));
			    }
								
			    (*returnColumnSizes)[*returnSize] = 4;
			    re[*returnSize] = (int*)malloc(sizeof(int)*4);
			    re[*returnSize][0] = nums[i];
			    re[*returnSize][1] = nums[j];
			    re[*returnSize][2] = nums[k];
			    re[*returnSize][3] = target-nums[i]-nums[j]-nums[k];
			    (*returnSize)++;
			}
	            }
	          }
                }
            }
        }
    }
   
    return re;
    
}

bool binarySearch(int* nums, int left, int right, int target) {
    int middle;
    if (target < nums[left] || target > nums[right])
        return false;
    while (left <= right) {
        middle = (right + left) / 2;
        if (nums[middle] == target) {
            return true;
        }
        else if (target > nums[middle]) {
            left = middle + 1;
        }
        else {
            right = middle - 1;
        }
    }
    return false;
}

下面是時間與空間之消耗

( 1 ) 雙指標法

Runtime: 48 ms, faster than 24.66% of C online submissions for 4Sum.
Memory Usage: 6.6 MB, less than 83.56% of C online submissions for 4Sum.

( 2 ) 搜尋法

Runtime: 56 ms, faster than 23.29% of C online submissions for 4Sum.
Memory Usage: 6.5 MB, less than 94.52% of C online submissions for 4Sum.

下一題連結 : LeetCode19. Remove Nth Node From End of List ( C ) – Medium

Add a Comment

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *