持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第11天,点击查看活动详情
前言
从零开始学习c++,每天起码做一道leetcode题目,在此记录,希望最后能够有所收获!
一、题目描述
给你一个整数数组 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的数,并返回一个二元数组。特别值得注意的是返回的三个数不能相同。这也是这个题目中最难的一个地方。为此需要在程序中做出诸多的限制。
在最开始看到题目的时候,我首先想到的就是排序。先将数组中的数字进行排序,再去掉其中重复的元素。最后再去寻找符合题目要求的i,j,k。然而这样实在是过于复杂了,我思来想去,是否能用双指针呢?但这个题目要求ijk三个量,似乎不可以哎。
最后看了一些高赞的思路,还是得用双指针。同样,先要观察根据题目的要求数组会有哪些规律出现。在该题目中,我们必须要注意重复的元素,但它们在数组中的位置是不确定的。所以排序是必要的。同时,在排好序后,可以设定i<j<k,此时,将i进行遍历,nums[i]应该小于0,否则不可能满足题意。
三、AC代码
class Solution{
public:
vector<vector<int>> threeSum(vector<int>& nums){
int k;
vector<vector<int>> ans;
sort(nums.begin(),nums.end());
for(int i=0;i<nums.size();i++)
{
if(i>0 && nums[i]==nums[i-1])
{
continue;
}
k = nums.size() - 1;
for (int j = i + 1; j < k;j++)
{
if(j>i+1 && nums[j]==nums[j-1])
{
continue;
}
while(nums[i]+nums[j]+nums[k]>0 && j<k)
{
k--;
}
if(j == k) break;
if(nums[i]+nums[j]+nums[k]==0)
{
ans.push_back({nums[i], nums[j], nums[k]});
}
}
}
return ans;
}
};
提交排名
四、总结
这道题目应该是我目前遇到的最难的题目了,同样巧妙的考验了双指针。但其中的逻辑更加复杂了。应该仔细地理清楚,确保下次能够做出来。