LeetCode 15.三数之和
15.三数之和
给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请你返回所有和为 0 且不重复的三元组。
注意:答案中不可以包含重复的三元组。
示例 1:
输入: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] 。
注意,输出的顺序和三元组的顺序并不重要。
示例 2:
输入:nums = [0,1,1]
输出:[]
解释:唯一可能的三元组和不为 0 。
示例 3:
输入:nums = [0,0,0]
输出:[[0,0,0]]
解释:唯一可能的三元组和为 0 。
提示:
3 <= nums.length <= 3000
-10^5 <= nums[i] <= 10^5
题解
做这道题目之前可以看看这道题目 167.两数之和 II
在两数之和中,我们通过使用左右两个指针在 O(n) 的时间内实现了寻找两个和为target的数
即使用 l 和 r 左右两个指针,假如nums[ l ] + nums[ r ] > target 则 r-- 若小于则 l++ 否则就找到了
-
类似的,对于三个数和为target,我们可以将其拆分为两个数和一个数的和
-
那么我们可以先枚举一个数作为三元组中最小的数,对于每一个数 nums[ i ],我们需要找到和为 target - nums[ i ] 的两个数,那么问题就回到了167.两数之和 II
需要注意的是,我们需要先将nums数组进行排序,否则无法在O(n)的时间内实现找到两个数
以及题目要求不能有重复的三元组,那么我们需要在枚举时略过相同的nums[ i ],同时,在找另外两个数时,也要略过相同的nums[ l ],nums[ r ]
优化
可以发现,由于我们枚举第一个数nums[ i ]是递增的,那么假如某一个nums[ i ]与剩下的最小的两个数之和大于0,那么之后的nums[ i ]肯定也是大于0的,所以就可以直接break掉循环
类似的,假如某一个nums[ i ]与剩下的最大的两个数之和仍旧小于0,那么就可以直接continue
代码如下↓
/**
* 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** threeSum(int* nums, int numsSize, int* returnSize, int** returnColumnSizes) {
int cmp(const void* a, const void* b)
{
return *(int*)a - *(int*)b;
}
qsort(nums,numsSize,sizeof(int),cmp);
int** arr = (int**)malloc(sizeof(int*)*99999);
int n=0;
for(int i=0;i<numsSize-2;i++)
{
if(i>0 && nums[i]==nums[i-1])
{
continue;
}
if(nums[i]+nums[i+1]+nums[i+2]>0)
{
break;
}
if(nums[i]+nums[numsSize-1]+nums[numsSize-2]<0)
{
continue;
}
int k=-nums[i];
int l=i+1;
int r=numsSize-1;
while(l<r)
{
if(nums[l]+nums[r]==k)
{
int* arrr = (int*)malloc(sizeof(int)*3);
arrr[0]=nums[i];
arrr[1]=nums[l];
arrr[2]=nums[r];
arr[n++]=arrr;
l++;
r--;
}
else if(nums[l]+nums[r]>k)
{
r--;
}
else
{
l++;
}
while(l>i+1 && l<r && nums[l]==nums[l-1])
{
l++;
}
}
}
*returnSize=n;
*returnColumnSizes=(int*)malloc(sizeof(int)*n);
for(int i=0;i<n;i++)
{
(*returnColumnSizes)[i]=3;
}
return arr;
}