赞
踩
给你一个整数数组 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
知识点:双指针、碰撞指针、排序
解析:
首先我们对于给定数组先进行排序,然后再使用双指针算法进行实现。
具体步骤
1.先进行排序。
2.从第一个数开始进行固定(当前位置为i)定义左右两个指针left,right,left每次从i的下一个位置开始,而right每次都从最右边开始。
3.每次求出left和right所指向的数的和,看看这个和是否等于i位置的倒数,如果大,right--,如果小,left++,直到找到匹配的数后,将结果存放到返回数组里,此时left++和right--同时进行。
4.为了避免出现重复结果,我们之前已经对数组进行了排序,假设此时left和right指向的值的和满足条件,又因为排序后连续的数会放到一起,所以left后面和right前面就会存在重复元素,此时我们需要跳过它,同时也要避免left>right,因为前面匹配后lefti已经移动了一次,如果用left后面的值当作判断的话,可能left的下一个元素是新元素,而此时left还在重复元素上,所以要有left前面的值进行判断,right也是一样,反过来就行。
5.匹配完后,i就要继续向下移动,而i也会存在重复元素的问题,也要记得查重。
- class Solution {
- public:
- vector<vector<int>> threeSum(vector<int>& nums) {
- vector<vector<int>> ret;//用于存储返回值
- sort(nums.begin(),nums.end());
- int n=nums.size();
- int i=0;
- while(i<n)
- {
- if(nums[i]>0) break;//小优化,因为i位置大于0的话,后面不可能有数相加等于它
- int left=i+1,right=n-1,target=-nums[i];
- while(left<right)
- {
- int sum=nums[left]+nums[right];
- if(sum>target) right--;
- else if(sum<target) left++;
- else
- {
- ret.push_back({nums[left],nums[right],nums[i]});
- left++;
- right--;
- while(left<right&&nums[left]==nums[left-1]) left++;
- while(left<right&&nums[right]==nums[right+1]) right--;
- }
- }
- i++;
- while(i<n&&nums[i]==nums[i-1]) i++;
- }
- return ret;
-
- }
- };
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。