题目
给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0
?找出所有满足条件且不重复的三元组。注意:答案中不可以包含重复的三元组。
例如, 给定数组 nums = [-1, 0, 1, 2, -1, -4],
满足要求的三元组集合为: [ [-1, 0, 1], [-1, -1, 2] ]
来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/3sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题解
- 暴力求解,遍历三遍,找到满足要求的三元组,时间复杂度O(n^3)
- 遍历两遍,在确定x,y的情况下,z=-x-y,所以第二遍可以使用map来查询-x-y:
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
if(nums.length<3){
return new ArrayList<List<Integer>>();
}
Set<List<Integer>> results = new HashSet<List<Integer>>();
Arrays.sort(nums);
for(int i =0;i<nums.length-2;i++){
if(i>0&&nums[i-1]==nums[i])continue;
Map map = new HashMap<Integer,Integer>();
for(int j=i+1;j<nums.length;j++){
if(!map.containsKey(nums[j])){
map.put(-nums[i]-nums[j],1);
}else{
results.add(Arrays.asList(nums[i], nums[j], (-nums[i]-nums[j])));
}
}
}
List<List<Integer>> res = new ArrayList<List<Integer>>();
for(List<Integer> result:results){
res.add(result);
}
return res;
}
}
- 一轮循环选择第一个数,然后在剩下的区间内使用左右指针(引用)从两边逼近,
class Solution { public List<List<Integer>> threeSum(int[] nums) { if(nums.length<3)return new ArrayList<List<Integer>>(); Arrays.sort(nums);//排序 List<List<Integer>> results = new ArrayList<List<Integer>>(); for(int i = 0; i<nums.length-2;i++){ if(i>0&&nums[i]==nums[i-1])continue;//去除相同的a if(nums[i]>0)break;//a大于0的情况下结束循环 int l = i+1;//左指针(b) int r = nums.length-1;//右指针(c) while(l<r){ int s = nums[i]+nums[l]+nums[r]; if(s<0)l++;//三数和小于零,左指针右移 if(s>0)r--;//三数和大于零,右指针左移 if(s==0){ results.add(Arrays.asList(nums[i],nums[l],nums[r])); while(l<r&&nums[l]==nums[l+1])l++;//去除重复的b,l不等于r避免第二次while 条件判断数组越界 while(l<r&&nums[r]==nums[r-1])r--;//去除重复的c,l不等于r避免第二次while 条件判断数组越界 l++; r--; } } } return results; } }