题目描述:
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。
注意:答案中不可以包含重复的三元组。
示例:
输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
解答描述:
该题要找到所有和为0且不重复的三元组。
首先,为了去重,需要先对数组进行一个排序,让所有相同元素聚集在一起,便于去重。在这里对数组进行qsort升序排序。(qsort是c语言内置的排序函数,使用之前需要先定义一个比较函数)
其次,要寻找满足条件的三元组(a,b,c),遵循先固定a,再找b,c的思想,而找b,c的过程,为了降低时间复杂度和便于去重,采用双指针法遍历,(双指针法常用于降低时间复杂度的遍历),定义两个指针,分别为l=i+1,r=numSize-1:则nums[i]=a,nums[l]=b,nums[r]=c;
1)当a+b+c>0时,说明需要减小值,则r--;
2)当a+b+c<0时,说明需要增大值,则l--;
3)当a+b+c=0时,说明找到了一个满足条件的三元组,存储在结果数组中;
注意,在遍历过程中,可能存在多个相同值的情况,这会导致三元组重复,所以需要分别对a,b,c,的遍历进行重复值得跳过。
此外,当最小值a都>0的时候,三元组的和不可能等于0,直接返回结果即可。
难点:个人觉得给定函数的参数的理解和使用比较晦涩。
int** ans=malloc(sizeof(int*)*numsSize*numsSize);
*returnColumnSizes = (int *)malloc(sizeof(int) * numsSize * numsSize);
*returnSize=0;
代码:
/**
* 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)//比较函数
{
return *(int*)a-*(int*)b;
}
int** threeSum(int* nums, int numsSize, int* returnSize, int** returnColumnSizes){
//排序
qsort(nums,numsSize,sizeof(int),comp);//qsort是C自带的使用快排的排序函数,必须自己写比较函数,C没有预置的sort函数
int** ans=malloc(sizeof(int*)*numsSize*numsSize);
*returnColumnSizes = (int *)malloc(sizeof(int) * numsSize * numsSize);
*returnSize=0;
for(int i=0;i<numsSize-2;i++)//i为a的下标
{
int l=i+1;//l为b的下标
int r=numsSize-1;//r为c的下标
if(nums[i]>0)//如果最小的a大于0,一定不存在满足条件的三元组
{
break;
}
if(i>0 && nums[i]==nums[i-1])//跳过重复的a
{
continue;
}
while(l<r)
{
int a=nums[i];
int b=nums[l];
int c=nums[r];
if(a+b+c>0)
{
r--;
}
else if(a+b+c<0)
{
l++;
}
else
{
ans[*returnSize]=malloc(sizeof(int)*3);
(*returnColumnSizes)[*returnSize]=3;
ans[*returnSize][0]=a;
ans[*returnSize][1]=b;
ans[*returnSize][2]=c;
(*returnSize)++;
while(l<r && nums[r]==nums[--r]);//跳过重复的b
while(l<r && nums[l]==nums[++l]);//跳过重复的c
}
}
}
return ans;
}