还是那句话,一个题思路很重要,没有思路等于无头苍蝇乱撞
题目要求:给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请
你返回所有和为 0 且不重复的三元组。
注意:答案中不可以包含重复的三元组。
第一种
我们可以采用暴力的手法,直接整三个循环,但是这样有很多弊端.
1.复杂度太高下来的话他需要O(n^3)。
2.最最关键的是不能重复。
第二种
我们可以采用排序加双指针的方法来完成。
1.排序的话个人建议不要用库里面的函数,我们能自己敲尽量自己敲,巩固我们的知识,当然我指的是快排之类的而不是那些冒泡选择排序。
2.双指针从左到右依次遍历,当我们从小到大将数字排好之后,如果检测到数字小则左边向右移一位,如果检测到数字大我们将右边指针向左移一位。
3.为了避免重复 我们在中间设立while循环 如果这个数和下一个数相等我们++,直至不相等再开始比较。
特别注意
本题需要返回的要求有三点
第一个意思就是:returnSize表示返回数组的行数。
第二个意思是:数组的大小以returnColumnSizes数组的形式返回。
第三个意思是:返回的数组和*columnSizes数组都必须进行mallocated,假设调用者调用free()。
下面看具体代码实现
首先排序这边我们使用快排:Quicksort(nums,0,numsSize-1);
int Sort(int* arr,int left,int right)
{
int i=left,j=right;
int temp=arr[i];
while(i<j)
{
while(i<j&&arr[j]>=temp)
j--;
arr[i]=arr[j];
while(i<j&&arr[i]<=temp)
i++;
arr[j]=arr[i];
}
arr[i]=temp;
return i;
}
void Quicksort(int* arr,int left,int right)
{
if(left<right)
{
int i=Sort(arr,left,right);
Quicksort(arr,left,i-1);
Quicksort(arr,i+1,right);
}
}
排序好之后
我们进行双指针查找,
由于力扣一直在跟我讲空间不够,所以我一气之下直接开了10w个空间
int** threeSum(int* nums, int numsSize, int* returnSize, int** returnColumnSizes)
{
int** res=(int**)malloc(sizeof(int)*100000);//存储答案
*returnColumnSizes=(int*)malloc(sizeof(int)*100000);//题目要求
Quicksort(nums,0,numsSize-1); //快排对数组进行排序
* returnSize=0; //返回的row
for(int i=0;i<numsSize;i++)//右左向右一个数一个数遍历
{
if(i>0&&nums[i]==nums[i-1]) //判断最初是否和前一个相等,避免重复项
{
continue;
}
int left=i+1,right=numsSize-1;
while(left<right) //双指针遍历
{
if(nums[left]+nums[right]==-nums[i]) //满足条件存入数组
{
res[*returnSize]=(int*)malloc(sizeof(int)*3); //开辟空间
(*returnColumnSizes)[*returnSize]=3;
res[*returnSize][0]=nums[i];
res[*returnSize][1]=nums[left];
res[*returnSize][2]=nums[right];
(*returnSize)++;
}
if(nums[left]+nums[right]<-nums[i]) //如果小于目标值则left++
{
while(left<right&&nums[left]==nums[left+1])//避免重复
left++;
left++;
}
else//如果大于目标值则right--
{
while(left<right&&nums[right]==nums[right-1]) //避免重复
right--;
right--;
}
}
}
return res;/;/返回结果数组
}
时间复杂度分析,从左到右遍历是O(n),双指针是O(n),嵌套则是O(n^2).