题目
给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请你返回所有和为 0 且不重复的三元组。
注意:答案中不可以包含重复的三元组。
示例:
输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
解释:
nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0 。
nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 。
nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。
不同的三元组是 [-1,0,1] 和 [-1,-1,2] 。
注意,输出的顺序和三元组的顺序并不重要。
输入:nums = [0,1,1]
输出:[]
解释:唯一可能的三元组和不为 0 。
输入:nums = [0,0,0]
输出:[[0,0,0]]
解释:唯一可能的三元组和为 0 。
思路
解法1:设置三层循环一次列举,时间复杂度为n^3。
解法2:首先对原始数组按从小到大排序,然后对每一个元素遍历,每次遍历再设立高低指针,设立二层循环遍历,如果和小于0,则高指针减一,和大于0则低指针加一。知道找到一组等于0的数,高低指针都减一和加一找下一组。其中为了保证不重复,找低指针时找第一个不重复的最小值,找高指针时找第一个不重复的最大值。
参数:
int* nums, 原始数组
int numsSize,原始数组大小
int* returnSize, 返回二维数组第一维大小
int** returnColumnSizes返回二维数组第二维大小(这里都是3,因为是三个数的和)
/**
* 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 partion(int *a,int left,int right){
int temp=a[left];
while(left<right){
while(left<right&&a[right]>temp) right--;
a[left]=a[right];
while(left<right&&a[left]<=temp) left++;
a[right]=a[left];
}
a[left]=temp;
return left;
}
void quickSort(int *a,int left,int right){
if(left<right){
int pos=partion(a,left,right);
quickSort(a,left,pos-1);
quickSort(a,pos+1,right);
}
}
int** threeSum(int* nums, int numsSize, int* returnSize, int** returnColumnSizes){
*returnSize=0;
int** result=(int**)malloc(sizeof(int *)*(numsSize+1)*6);
//按照从小到大排序
quickSort(nums,0,numsSize-1);
int first,second,third;
if(numsSize<3) return result;
for(first=0;first<numsSize-2;first++){
if(nums[first]+nums[first+1]+nums[first+2]>0) break;//此时最小的三个数的和都大于0,没有满足条件的了
if((first>0)&&nums[first]==nums[first-1]){
continue;//和上一次枚举的值重复了,跳过此次循环
}
for(second=first+1,third=numsSize-1;second<third;){
if((third)<numsSize-1&&nums[third]==nums[third+1]){
third--;
continue;//找到从右往左第一个不同的third,即排除third指针的重复值
}
if((second!=(first+1))&&nums[second]==nums[second-1]){
second++;
continue;//即排除second指针的重复值
}
if((nums[first]+nums[second]+nums[third])>0){
third--;//大了取个更小的数
}else if((nums[first]+nums[second]+nums[third])<0){
second++;//小了取个更大的值
}else{
//满足要求
result[*returnSize]=(int*)malloc(sizeof(int)*3);
result[*returnSize][0]=nums[first];
result[*returnSize][1]=nums[second];
result[*returnSize][2]=nums[third];
(*returnSize)++;
second++;
third--;
}
}
}
*returnColumnSizes=(int*)malloc(sizeof(int)*(*returnSize));
for(int i=0;i<*returnSize;i++){
(*returnColumnSizes)[i]=3;
}
return result;
}