力扣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
-105 <= nums[i] <= 105
思路解析
在这我给大家分享一下我的思路,我的解法偏向于暴力没有什么特别的算法。
因为返回的不是下标,所以可以先将该数组进行排序,然后就可以开始查找三元组了,利用三个元素之和进行判断就行,在进行查找之前可以进行一点优化,如果遍历到的元素 与它后两个元素之和大于零 或者 与该数组最后两个元素相加小于0 的话,说明该数组剩余的元素最小三元和都大于零,以及最大三元组都小于0,可以直接退出遍历。
查找时,从剩下的元素的头和尾向中间寻找,如果三元组和大于0,则将大的值向左移,如果小于0则将小的数向右移,结束条件为小的数下标大于等于大的数的下标,找到和为0的三元组时,将该三元组放入答案数组,如果还有剩下的元素没有查询时,由于不能包含重复三元组,所以需要将当前查询值移到不同的值继续查询。
代码实现
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>>ans;//记录答案的数组
sort(nums.begin(),nums.end());//将nums数组排序
int n=nums.size();//数组元素数量
for(int i=0;i<n-2;i++)
{
int x=nums[i];//当前元素值
if(i&&x==nums[i-1])continue;//如果遍历到的值与前一个相同则不需要再次寻找答案
if(x+nums[i+1]+nums[i+2]>0)break;//如果最小的三个数相加都大于0,那么在所剩元素中没有和为0的三元组
if(x+nums[n-2]+nums[n-1]<0)continue;//如果最大三个数相加都小于0,那么在所剩元素中没有和为0的三元组
int j=i+1,k=n-1;//j为所剩元素中的最小值,k为最大值
while(j<k)//由于一个元素可能有几个三元组,所以当j<k就应该继续寻找
{
int flag=x+nums[j]+nums[k];//当前三元和
if(flag>0)k--;//如果大了则将k左移
else if(flag<0)j++;//小了将j右移
else
{
ans.push_back({x,nums[j],nums[k]});//找到答案时将该三元组放入答案数组
for (j++; j < k && nums[j] == nums[j - 1]; j++);//将j移动到下一个不同的值
for (k--; k > j && nums[k] == nums[k + 1]; k--);//将k移动到下一个不同的值
}
}
}
return ans;
}
};
原文地址:https://blog.csdn.net/2301_80505422/article/details/143992387
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!