• 四数之和


    给定一个包含 n 个整数的数组 nums 和一个目标值 target,判断 nums 中是否存在四个元素 a,b,c 和 d ,使得 a + b + c + d 的值与 target 相等?找出所有满足条件且不重复的四元组。

    注意:

    答案中不可以包含重复的四元组。

    示例:

    给定数组 nums = [1, 0, -1, 0, -2, 2],和 target = 0。

    满足要求的四元组集合为:
    [
      [-1,  0, 0, 1],
      [-2, -1, 1, 2],
      [-2,  0, 0, 2]
    ]


    方法一:
    解题思路:
    (1)首先我们回忆一下之前所遇到的三数之和的问题,我们的解题思路是,先排序(升序),定住最左边数组下标a,然后在其余的部分用左右指针开始访问数组
    假设是left与right指针,left=a+1, right=array_size-1; 接着计算sum=nums[a]+nums[left]+nums[right],如果sum> target, right--,右指针向左移动;
    如果sum < target, left++, 左指针向右移动; 如果sum == target, 记录下来当时的组合,count++, 做计数,可以知道有多少种组合最后。
    在三数之和中,我们需要关心的就是去重的问题,题目要求我们,去掉重复的组合,首先针对外层循环a来说,只要a!= 0 && nums[a] == nums[a-1]的都应该去掉,
    针对内层循环来说,只要将while(left<right && nums[left]== nums[left+1])left++和while(left<right && nums[right]== nums[right-1])right--
    作为其中的处理逻辑,就可以去掉内层中的重复的部分;
    (2)那么现在我们来说一下该题,四数之和, 首先也是排序, 然后定住数组的最左边的两个元素a与b, 其中b=a+1, a从数组下标为0开始,
    相当于两层循环,其中内层循环靠左右指针来完成, left=b+1, right=array_size-1; 接着计算sum=nums[a]+nums[b]+nums[left]+nums[right],接下来
    根三数之和的左右指针移动方法一样,去重也是一样的
    代码实现:
    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){
        int *tmp_array=NULL;
        int **ret_array=NULL;
        int count=0;
        if(numsSize == 0 || nums == NULL){
            goto end;
        }
        qsort(nums, numsSize, sizeof(int), cmp);
        tmp_array=malloc(sizeof(int)*50000);
        memset(tmp_array, 0sizeof(int)*50000);
        if(numsSize == 0){
            goto end;
        }
    int jj=0;
    for(;jj<numsSize-3;jj++){
        
        if(jj!=0 && nums[jj] == nums[jj-1]) {
                continue;
        }
        int ii=jj+1;
        for(;ii<numsSize-2;ii++){

            if(ii!=jj+1 && nums[ii] == nums[ii-1]) {
                continue;
            }
            
            int left=ii+1;
            int right=numsSize-1;
            while(left < right){
                int sum=nums[jj]+nums[ii]+nums[left]+nums[right];
                if(sum==target){
            
                    int *tmp=(char *)tmp_array+sizeof(int)*4*count;
                    tmp[0]=nums[jj];
                    tmp[1]=nums[ii];
                    tmp[2]=nums[left];
                    tmp[3]=nums[right];
                    count++;
                    
                    while(left<right && nums[left]== nums[left+1])left++;
                    while(left<right && nums[right]== nums[right-1])right--;
                    left++;
                    right--;
                }else if(sum <target){
                    left++;

                }else if(sum>target){
                    right--;
                }
            
            }
        }
    }


    end:
        if(count!= 0){
            *returnSize=count;
            int *tmp=NULL;
            tmp=malloc(sizeof(int)*count);
            int ii=0;
            for(;ii<count;ii++){
                tmp[ii]=4;
            }
            *returnColumnSizes=tmp;
    #if 1
            ret_array=malloc(sizeof(int *) *count);
            ii=0;
            for(;ii<count;ii++){
                ret_array[ii]=(char *)tmp_array+sizeof(int)*4*ii;
            }
    #endif
        }else{
            *returnSize=0;
            *returnColumnSizes=NULL;
        }

        return ret_array;

    }
    来源:力扣(LeetCode)
    链接:https://leetcode-cn.com/problems/4sum
    著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
    代码实现:
  • 相关阅读:
    牛客练习赛64 D-宝石装箱(容斥定律,背包)
    CF-GYM-[2019 USP Try-outs] 部分题解
    [Codeforces Round #642 (Div. 3)] ABCDEF题解
    [NCD 2019] G. Ali and the Breakfast (解析几何)
    [AtCoder Beginner Contest 165] E
    [Educational Codeforces Round 86 (Rated for Div. 2)] E. Placing Rooks (组合数学,容斥定律)
    [AtCoder Beginner Contest 164] -E
    牛客算法周周练3 C -小雨坐地铁(分层最短路)
    HDU 5726 GCD (RMQ + 二分)
    Codeforces Round #362 (Div. 2) C. Lorenzo Von Matterhorn (类似LCA)
  • 原文地址:https://www.cnblogs.com/pigdragon/p/12444038.html
Copyright © 2020-2023  润新知