LeetCode (力扣) 15. 3Sum (C) - Medium ( 排序+搜寻法 )

同步发于 JuzerTech 网站,里面有我软、硬件学习的纪录与科技产品开箱,欢迎进去观看。

题目为给定一串数字,输出所有三个数字相加为 0 的数字组合。

这题有速度的问题,建议使用排序与搜寻方法。

 

题目与范例如下

Given an integer array nums, return all the triplets [nums[i], nums[j], nums[k]] such that i != j, i != k, and j != k, and nums[i] + nums[j] + nums[k] == 0.

Notice that the solution set must not contain duplicate triplets.

Example 1:

Input: nums = [-1,0,1,2,-1,-4]
Output: [[-1,-1,2],[-1,0,1]]
Example 2:

Input: nums = []
Output: []
Example 3:

Input: nums = [0]
Output: []

Constraints:

0 <= nums.length <= 3000
-105 <= nums[i] <= 105


解题策略为先排序,这样在 for 回圈时能跳过三个都是正整数的组合。

我采用的排序法是 merge sort , sortsub是用于 merge sort 的递归函式。

程式碼中採用了兩層的 for 第一層控制第一個數字 ( i ), 從 0 ~ ( n - 3 ) , for 的第二層控制第二個數字 ( j ), 從 ( i + 1 ) ~ ( n - 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** threeSum(int* nums, int numsSize, int* returnSize, int** returnColumnSizes){
    
    
    *returnSize = 0;            // number of return pairs
    int step = 512;              // each memory alloc
    *returnColumnSizes = (int*)malloc(sizeof(int*)*step); 
    int** re = (int**)malloc(sizeof(int*)*step);

    
    mergeSort(nums, numsSize);

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

                        (*returnColumnSizes)[*returnSize] = 3;
                        re[*returnSize] = (int*)malloc(sizeof(int)*3);
                        re[*returnSize][0] = nums[i];
                        re[*returnSize][1] = nums[j];
                        re[*returnSize][2] = 0-nums[i]-nums[j];
                        (*returnSize)++;               
                    }
                }
            }
        }
    }
   
    return re;
}


void mergeSort(int* num, int numsSize) {
    sortsub(num, 0, numsSize - 1);
}

void sortsub(int* num, int low, int high) {
    if ((high - low) >= 1) {
        int middleL = (low + high) / 2;
        int middleR = middleL + 1;
        sortsub(num, low, middleL);
        sortsub(num, middleR, high);
        merge(num,low,middleL,middleR,high);
    }

}

void merge(int *num,int low,int middleL,int middleR, int high) {
    int combinedIndex = 0, leftIndex = low, rightIndex = middleR;
    int* tempArray = (int*)malloc(sizeof(int) * (high - low + 1));

    while (leftIndex <= middleL && rightIndex <= high) {
        if (num[leftIndex] < num[rightIndex]) {
            tempArray[combinedIndex++] = num[leftIndex++];
        }
        else
            tempArray[combinedIndex++] = num[rightIndex++];    
    }

    if (leftIndex > middleL) {
        while (rightIndex <= high) {
            tempArray[combinedIndex++] = num[rightIndex++];
        }
    }
    else {
        while (leftIndex <= middleL) {
            tempArray[combinedIndex++] = num[leftIndex++];
        }
    }

    for (int i = low; i <= high; i++) {
        num[i] = tempArray[i - low];
    }
}

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;
}

 

下方为时间与空间之消耗

Runtime: 216 ms, faster than 25 % of C online submissions for Roman to Integer.

Memory Usage: 36.3 MB, less than 20.51 % of C online submissions for Roman to Integer.

( 本题一次配置的记忆体空间尽量大一点,太小需要多次配置记忆体会大幅提升执行的时间。 )

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值