3Sum
Given an array nums
of n integers, are there elements a, b, c in nums
such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.
Note:
The solution set must not contain duplicate triplets.
Example:
Given array nums = [-1, 0, 1, 2, -1, -4], A solution set is: [ [-1, 0, 1], [-1, -1, 2] ]
3 Sum, two sum 进阶问题,看到题目第一想法就是把这个转化成2 sum 类型,也就是说先fix一个数,然后在数组寻找俩个数的合为负的fix的这个数。在套用2 sum的算法时候发现会产生很多的重复解。于是又对这些解每次插入到结果前先排序,确保如果有重复解,解的样子一致。最后在输出结果的时候利用hashset去除重复解。但是最后超时。。
public class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> result = new ArrayList<>();
if(nums.length < 3) return result;
for(int temp = 0; temp < nums.length; temp++){
HashMap<Integer,Integer> map = new HashMap<>();
for(int i = nums.length-1; i>=0; i--){
if(i != temp){
int complete = 0 - nums[temp] - nums[i];
if(map.containsKey(complete)){
int[] input = new int[]{nums[i], nums[temp], complete};
Arrays.sort(input); // 排序确保解的形式一致
result.add(Arrays.asList(input[0], input[1], input[2]));
}
map.put(nums[i], i);
}
}
}
HashSet h = new HashSet(result); //去除重复解
result.clear();
result.addAll(h);
return result;
}
}
这种方法不行的话,所以我考虑像另外一道two sum一样,采用two pointer, 不过需要先要把数组排列一下。
因为现在的数组是排列好的,所以我们可以做个剪枝优化,即每次优先判断fix的那个数是否是大于0,如果大于0就不用往下循环,因为后面数都肯定大于0,结果不可能为0。然后我们需要考虑一个去除重复问题。由于数组已经排列好,重复解应该是重复fix了同一个数才产生, 所以只要每次判断是否当前fix数的值等于上一个fix数的值就能去除重复解。
public class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> result = new ArrayList<>();
if(nums.length<3){
return result;
}
Arrays.sort(nums);
for(int fix = 0; fix < nums.length-2; fix++){
if(nums[fix] > 0){
break;
}
if (fix != 0 && nums[fix] == nums[fix - 1]) continue;
int start = fix + 1;
int end = nums.length -1;
int sum = 0 - nums[fix];
while(start < end){
int temp = nums[start] + nums[end];
if(temp == sum){
result.add(Arrays.asList(nums[fix], nums[start], nums[end]));
while((end-1)>=start && nums[end] == nums[--end]);
}
if(temp < sum){
start++;
}
if(temp > sum) {
end--;
}
}
}
return result;
}
}