N数之和的问题

【LeetCode】


N个数之和问题


一, N个数之和问题

  1. 三数之和
    给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有满足条件且不重复的三元组。

注意:答案中不可以包含重复的三元组。

示例:

给定数组 nums = [-1, 0, 1, 2, -1, -4],

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

一般我们是想到排列组合 列举有多少个组合

如果需要再找个上面优化,需要排除一些重复的组合,找个怎么做呢!

通常我们会排序后, 找出重复的数据比较容易

下面给出 先排序后 再找出不重复的数据 来计算比较容易的


#include <string.h>
#include <stdio.h>
#include <stdlib.h>
int compare (const void *a ,const void *b)
{
	int *aa=(int * ) a,*bb = (int * )b;
	if( * aa >* bb) 
    {
        return 1;
    }
	if( * aa == * bb) 
    {
        return 0;
    }
	if( * aa < *bb) 
    {
        return -1;
    }
    return 0;
}

int** threeSum(int* nums, int numsSize, int* returnSize, int** returnColumnSizes)
{
    
        *returnSize = 0;
    if (nums == NULL || numsSize < 3 )
    {
        return NULL;
    }
    int alloc_size = 1;
    int* *arrayy = malloc(alloc_size * sizeof(int*));
    *returnColumnSizes = malloc(alloc_size * sizeof(int));
    qsort(&nums[0] , numsSize, sizeof(int), compare);
   
   
   
    
    int array_index = 0;
    int b = 0;
    int c = 0;
    for (int a = 0; a < numsSize; ++a)
    {
        if (a == 0 || a > 0 && nums[a] != nums[a-1])
        {
            b = a + 1;
            c = numsSize - 1;
            while (b < c)
            {
                int diff = nums[a] + nums[b];
                //这里数组是排序过的所以比较容易排除重复的数据 和 不符合要的数据
                if ( diff + nums[c]  > 0)  // 比较大小来看这个数组中还有没有数字
                {
                    while (--c > b && nums[c] == nums[c+1]){}
                }
                else if (diff + nums[c] < 0) 
                {
                    while (++b < c && nums[b] == nums[b-1]){}
                }
                else 
                {
                    (*returnColumnSizes)[ *returnSize] =3;
                    arrayy[ *returnSize] = malloc(3 * sizeof(int));
                    arrayy[ *returnSize][0] = nums[a];
                    arrayy[ *returnSize][1] = nums[b];
                    arrayy[ *returnSize][2] = nums[c];
                    (*returnSize)++;
                    while (--c > b && nums[c] == nums[c+1]){}
                    while (++b < c && nums[b] == nums[b-1]){}

                    //内存不足时扩容 2倍扩大
                    if (*returnSize == alloc_size) 
                    {
                        alloc_size = 2 * alloc_size;
                        arrayy = realloc(arrayy, alloc_size*  sizeof(int*));
                        (*returnColumnSizes) = realloc((*returnColumnSizes),  alloc_size* sizeof(int));
                    }
                       
                }
                
            }
        }
        
    }
  
   
    return arrayy;
}

int main(int argc, char *argv[])
{

    int array[] = { -1, 0, 1, 2, -1, -4 };// {0, 0, 0, 0};
   
	
	int retsize = 0;
	int * retclomueesize = NULL;
	int ** retarray = threeSum(&array[0], 10, &retsize, &retclomueesize);
	
	for (int i = 0;  i < retsize; ++i)
	{
		printf("[%d][%d][%d]\n", retarray[i][0], retarray[i][1], retarray[i][2]);
	}

	

    return 0;
}

二, 最接近的三数之和

给定一个包括 n 个整数的数组 nums 和 一个目标值 target。找出 nums 中的三个整数,使得它们的和与 target 最接近。返回这三个数的和。假定每组输入只存在唯一答案。

示例:

输入:nums = [-1,2,1,-4], target = 1
输出:2
解释:与 target 最接近的和是 2 (-1 + 2 + 1 = 2) 。

提示:

3 <= nums.length <= 10^3
-10^3 <= nums[i] <= 10^3
-10^4 <= target <= 10^4

找个最接近某个数在我们数组上就有绝对值

|nums[1] + nums[ 2] + nums[3] - target|

所以我们就使用abs函数


int compare(const void *a, const void *b)
{
	int *aa = (int *)a, *bb = (int *)b;
	if (*aa > * bb)
	{
		return 1;
	}
	if (*aa == *bb)
	{
		return 0;
	}
	if (*aa < *bb)
	{
		return -1;
	}
	return 0;
}
int threeSumClosest(int* nums, int numsSize, int target)
{
	int min_diff = 0X7FFFFF;
	if (nums == NULL || numsSize < 3)
	{
		return min_diff;
	}

	qsort(&nums[0], numsSize, sizeof(int), compare);
	for (int a = 0; a < numsSize - 2; ++a)
	{
		int b = a + 1;
		int c = numsSize - 1;

		while (b < c)
		{
		
			int diff = nums[a] + nums[b] + nums[c] - target;
			// 绝对值比较
			if (abs(diff) < abs(min_diff))
			{
				min_diff = diff;
			}
			if (diff < 0)
			{
				while (++b < c && nums[b] == nums[b - 1]) {}
			}
			else if (diff > 0)
			{
				while (b < --c && nums[c] == nums[c + 1]) {}
			}
			else
			{
				return target;
			}
		}
	}
	
	return target + min_diff;


}
int main(int argc, char *argv[])
{

    int array[] = { -1,2,1,-4 };

	printf("sum = %d\n",  threeSumClosest(&array[0], 4, 1));

	

    return 0;
}

三,总结:

  1. 几个数中的最小或者最大值 , 就是使用排列组合
  2. 去除重复的数据就需要对数据进行排序 找出过滤重复组合

猜你喜欢

转载自blog.csdn.net/Poisx/article/details/109437459