【C语言】LeetCode 18 4Sum

题目:

Given an array S of n integers, are there elements abc, 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: 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]
]

思路:

采用循环或者递归,逐个查找计算总和。

代码一(函数循环,12ms)

/**
 * 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) {
    int flag;
    int temp;
    int min;
    int **output=NULL;
    int last1,last2,last3,last4;//用于记录上一次取值
    //用于判断是否判断此次取值与上次取值是否相同
    int flag1=0;
    int flag2=0;
    int flag3=0;
    int flag4=0;
    int sizereturn=0;
    //先进行排序
    for(int i=0;i<numsSize;i++)
    {
        min=nums[i];
        for(int j=i;j<numsSize;j++)
        {
            if(min>=nums[j])
            {
                flag=j;
                min=nums[j];
            }
        }
        temp=nums[flag];
        nums[flag]=nums[i];
        nums[i]=min;
    }
    for(int i=0;i<numsSize-3;i++)
    {
        if(flag1&&nums[i]==last1)continue;//改变第一个值时不可与前一个取值相同,否则重复
        if(4*nums[i]>target)break;
        if((nums[i]+nums[numsSize-1]+nums[numsSize-2]+nums[numsSize-3])<target)continue;
        flag2=0;
        for(int j=i+1;j<numsSize-2;j++)
        {
            if(flag2&&nums[j]==last2)continue;//改变第二个值时不可与前一个取值相同,否则重复
            if((nums[i]+3*nums[j])>target)break;
            //排序之后,最后的值最大,如果加上最后的值仍小于target,则跳过
            if((nums[i]+nums[j]+nums[numsSize-2]+nums[numsSize-1])<target)continue;
            flag3=0;
            for(int k=j+1;k<numsSize-1;k++)
            {
                if(flag3&&nums[k]==last3)continue;//改变第三个值时不可与前一个取值相同,否则重复
                if((nums[i]+nums[j]+nums[k]+nums[k])>target)break;
                if((nums[i]+nums[j]+nums[k]+nums[numsSize-1])<target)continue;
                flag4=0;
                for(int m=k+1;m<numsSize;m++)
                {
                    if(flag4&&nums[m]==last4)continue;
                    if(nums[i]+nums[j]+nums[k]+nums[m]==target)
                    {
                        sizereturn++;
                        output=(int**)realloc(output,sizereturn*sizeof(int*));
                        *(output+sizereturn-1)=(int*)malloc(4*sizeof(int));
                        output[sizereturn-1][0]=nums[i];
                        output[sizereturn-1][1]=nums[j];
                        output[sizereturn-1][2]=nums[k];
                        output[sizereturn-1][3]=nums[m];
                    }
                    else if((nums[i]+nums[j]+nums[k]+nums[m])>target)break;
                    flag4=1;
                    last4=nums[m];
                }
                flag3=1;
                last3=nums[k];
            }
            flag2=1;
            last2=nums[j];
        }
        flag1=1;
        last1=nums[i];
    }
    *returnSize=sizereturn;
    return output;
}


代码二(递归函数,19ms)

/**
 * Return an array of arrays of size *returnSize.
 * Note: The returned array must be malloced, assume caller calls free().
 */
void findtarget(int* nums, int numsSize, int target,int output[],int index,int n,int ***returnarr,int *returnSize)
{
    int flag=0;
    int last;
    if(n==1)
    {
        for(int i=index;i<numsSize-n+1;i++)
        {
            if(flag&&last==nums[i])continue;
            if(-1*nums[i]+target==0)
            {
                (*returnSize)++;
                output[n-1]=nums[i];
                *returnarr=(int**)realloc(*returnarr,(*returnSize)*sizeof(int*));
                *(*returnarr+(*returnSize)-1)=(int*)malloc(4*sizeof(int));
                for(int j=0;j<4;j++)
                {
                    (*returnarr)[*returnSize-1][j]=output[3-j];
                }
            }
            last=nums[i];
            flag=1;
        }
    }
    else
    {
        for(int i=index;i<numsSize-n+1;i++)
        {
            int sum=nums[i];
            int sum2;
            if(flag&&last==nums[i])continue;
            output[n-1]=nums[i];
            for(int si=numsSize-1;si>(numsSize-n);si--)
                sum+=nums[si];
            sum2=n*nums[i];
            if(sum2>target)break;
            if(sum<target)continue;
            findtarget(nums,numsSize,target-nums[i],output,i+1,n-1,returnarr,returnSize);
            last=nums[i];
            flag=1;
        }
    }
}

int** fourSum(int* nums, int numsSize, int target, int* returnSize) {
    int output[4];
    int **returnarr=NULL;
    int num=0;
    int flag=0;
    int last;
    int min;
    int minflag;
    int temp;
    *returnSize=0;
    for(int i=0;i<numsSize;i++)
    {
        min=nums[i];
        for(int j=i;j<numsSize;j++)
        {
            if(min>=nums[j])
            {
                minflag=j;
                min=nums[j];
            }
        }
        temp=nums[minflag];
        nums[minflag]=nums[i];
        nums[i]=min;
    }
    findtarget(nums,numsSize,target,output,0,4,&returnarr,returnSize);
    return returnarr;
}

思路拓展:

采用递归函数稍加修改可适用于K-SUM问题

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值