题目来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/3sum
给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。
注意:答案中不可以包含重复的三元组。
示例:
给定数组 nums = [-1, 0, 1, 2, -1, -4],满足要求的三元组集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]
参考力扣当中的c语言题解进行编程。首先将数组进行从小到大的排序,方便快速判断当三数之和大或小时,应该向前还是向后移动数。参考c语言中的排序函数,首先对数组进行排序。
```c
int comp(const void*a,const void*b)//用来做比较的函数。
{
return *(int*)a-*(int*)b;
}
排序之后,设置迭代的初始值i为0,设置zuo与you作为辅助变量。为放置三元组的数组分配空间。之后进行判定,当前元素为nums[i],当值大于零时,直接退出迭代,此时i之后的元素无法与其形成三元组(都大于零),当zuo与you大小相反时,不能进行迭代。
之后进行循环,将nums[i]与nums[zuo],nums[you]相加,若值小于0,则为了增加和,令zuo 向前一个元素,反之令you退回一个元素,直到zuo与you相差1,结束循环。若找到三元组,则将三元组加入到返回数组,并且增加列数。并且为了避免重复,当zuo向后的一个元素与zuo所在的nums[zuo]相同时,退后一个元素,直到zuo 后的元素与zuo不重复,you和i也同样成立,最终得到不重复的三元组集合。
```c
int** threeSum(int* nums, int numsSize, int* returnSize, int** returnColumnSizes){
*returnSize=0; //满足条件的三元组数为0
if(numsSize<3) return 0; //当数组元素较少时直接返回
int** rr = (int**)malloc(sizeof(int*) * (numsSize)*(numsSize)); //设置返回数组
*returnColumnSizes = (int*)malloc(sizeof(int) * (numsSize)*(numsSize)); //设置列数
int i=0,zuo=i+1,you=numsSize-1; //设置初值和zuo,you两个辅助变量
qsort(nums,numsSize,sizeof(int),comp); //调用排序函数
while((i<(numsSize-2))&&(nums[i]<=0)) //当前元素大于零时直接输出,因为剩余可以匹配的数都为正
{
zuo=i+1;
you=numsSize-1;
while(zuo<you) //设置判定条件
{
if(nums[i]+nums[zuo]+nums[you]<0) //若当前和较小,需要加上一个更大的数,下面同理
{
zuo++;
}
else if(nums[i]+nums[zuo]+nums[you]>0)
{
you--;
}
else
{
rr[*returnSize] = (int*)malloc(sizeof(int) * 3); //获得三元组,给返回数组分配空间
(*returnColumnSizes)[*returnSize] = 3; //列数为3
rr[*returnSize][0]=nums[i]; //将三元组输入数组
rr[*returnSize][1]=nums[zuo];
rr[*returnSize][2]=nums[you];
(*returnSize)++; //行数增加,三元组数增加
while(nums[zuo]==nums[++zuo]&&zuo<you) {} //当含有重复项时,跳过重复项进行迭代
while(nums[you]==nums[--you]&&zuo<you) {}
}
}
while(nums[i]==nums[++i]&&(i<(numsSize-2))) {} //当i对应的数组元素重复时,跳过
}
return rr; //返回三元数组集合
}
在写代码时,要注意边界条件的设置,避免出现调用参数时超出数组范围。