题目描述
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有满足条件且不重复的三元组。
注意:答案中不可以包含重复的三元组。
示例:
给定数组 nums = [-1, 0, 1, 2, -1, -4],
满足要求的三元组集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/3sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
白话题目:
一个数组,找到里面三个数的和为0就行,都得找出来,之后不能有重复的。
算法:
(1)快排输入数组,调用系统的Qsort函数,是根据二分法写的,其时间复杂度为n*log(n)
void qsort(void* base,size_t num,size_t width,int(__cdecl*compare)(const void*,const void*));
参数: 1 待排序数组,排序之后的结果仍放在这个数组中
2 数组中待排序元素数量
3 各元素的占用空间大小(单位为字节)
4 指向函数的指针,用于确定排序的顺序(需要用户自定义一个比较函数)
讲普通话, qsort(nums, numsSize, sizeof(int), comp);//用自带的排序
(2)结果长啥样子
6个数,取三个数,如何都取出来形成结果是不是得很多,够用了吧,不动脑筋的就来个numsSize*numsSize,这里面得去重,不符合之类的处理。
还有leetcode这里一个特殊参数的处理,也是加强了对于二维指针的理解,详见代码详细讲解视频
(3)优化提速
暴力肯定超时,就用双指针,以第一个点为核心,之后移动L=i+1,R=numsSize-1;
详细解释关注 B站 【C语言全代码】学渣带你刷Leetcode 不走丢 https://www.bilibili.com/video/BV1C7411y7gB
C语言完全代码
#include <stdio.h>
#include <stdlib.h>
/**
* 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 comp(const void *_a,const void *_b) //const void *a这是定义了一个指针a,a可以指向任意类型的值,但它指向的值必须是常量
{
int* a = (int*)_a; // 强制转换成整型指针
int* b = (int*)_b;
return *a - *b; //默认升序排列(从小到大),如果想降序排列返回*b-*a即可
}
//int** threeSum(int* nums, int numsSize, int* returnSize)
//{
int** threeSum(int* nums, int numsSize, int* returnSize, int** returnColumnSizes)
{
*returnSize = 0; //*p 取值
//当输入元素不足3个
if(numsSize < 3)
{
return 0;
}
//初始化结果数组为numsSize行*numsSize列的
int** returnArray = (int**)malloc(sizeof(int*) * (numsSize)*(numsSize)); //Cn3就够了
// *returnColumnSizes = (int*)malloc(sizeof(int) * (numsSize)*(numsSize));
*returnColumnSizes = (int*)malloc(sizeof(int) * (numsSize)*(numsSize)); //returnColumnSizes【】【】 returnColumnSizes[]
//*returnColumnSizes = (int*)calloc(sizeof(int), *returnSize); //层序的最后要是这么写就没有事
// for (int i = 0; i < *returnSize; i++) {
// (*returnColumnSizes)[i] = 3;
// }
qsort(nums, numsSize, sizeof(int), comp);//用自带的排序
int i;
for( i=0; i < numsSize; i++)
{
//若排序后的数组首元素大于0 ,则肯定不存在三元组
if(nums[0] > 0)
{
return NULL;
}
if(i > 0 && nums[i] == nums[i-1]) //之前的找过了,再找会一样,去重
{
continue;
}
int L = i+1, R = numsSize-1;
while(L < R)
{
if(nums[i] + nums[L] + nums[R] == 0)
{
// 每次找到一组,二级指针就分配三个空间
returnArray[*returnSize] = (int*)malloc(sizeof(int) * 3); //从0行开始
(*returnColumnSizes)[*returnSize] = 3; //
returnArray[*returnSize][0] = nums[i];
returnArray[*returnSize][1] = nums[L];
returnArray[*returnSize][2] = nums[R];
(*returnSize)++;
//去重2:左指针移动到最后1个相同元素
while(L < R && (nums[L] == nums[L+1]))
{
L++;
}
//去重3:右指针移动到最后1个相同元素
while(L < R && (nums[R] == nums[R-1]))
{
R--;
}
//双指针例行移动1位
L++;
R--;
}
else if(nums[i] + nums[L] + nums[R] < 0)
{
//调大
L++;
}
else
{
R--;
}
}
}
return returnArray;
}
int main()
{ printf("测试数据的个数 6\n");
int numsSize;
scanf("%d",&numsSize);
int nums[numsSize];
int i,j;
printf("测试数据 -1, 0, 1, 2, -1, -4 \n");
for(i=0; i<numsSize; i++)
{
scanf("%d",&nums[i]);
}
int **returnColumnSizes =(int**)malloc(sizeof(int*)*numsSize);
int returnSize=0;
//输出
int** resultArray = threeSum( nums, numsSize, &returnSize,returnColumnSizes);
printf("%d\n",returnSize);
for(i=0; i<returnSize; i++)
{
for ( j = 0; j < (*returnColumnSizes)[i]; j ++)
{
printf("%d ",resultArray[i][j]) ;
}
printf("\n");
}
return 0;
}