Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.
Note:
Elements in a triplet (a,b,c) must be in non-descending order. (ie, a ≤ b ≤ c)
The solution set must not contain duplicate triplets.
For example, given array S = {-1 0 1 2 -1 -4},
A solution set is:
(-1, 0, 1)
(-1, -1, 2)
问题:求数组中,所有和为0 的三个元素。
解题思路:
直接用三重循环扔上去超时了,然后在网上看到使用双指针的算法,理解后,把这道题解决了。
第一步,对数组排序。
第二步,
对于元素 S[i] , 最后的答案可以分为两种,包含 S[i] 的,和不包含 S[i] 的。当包含 S[i] 的情况都找到后,后续就可以不用在考虑 S[i] 。
对于 S[i] , l = i+1, r = len-1 。若 s[i] + S[l] + S[r] == 0, 则为原问题的一个解。
当 S[i] + S[l] > -S[r] 时,则 r--
当 S[i] + S[l] < -S[r] 时,则 l++
当 S[i] + S[i] = -S[r] 时, 表示是原问题的一个解,则 l++, r--;(这里使用的一层循环,我使用的两层,可以通过测试)
第三步,性能优化。同样根据分析1,若 S[i] == S[i+1],可以跳过。
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> result = new ArrayList<List<Integer>>();
//先排序,则可以简单判断第一个元素重复,以及避免三个元素一样只是顺序不同
Arrays.sort(nums);
List<Integer> subList = new ArrayList<Integer>();
for(int i=0; i<nums.length-2; i++){
<span style="white-space:pre"> </span>//判断nums[i]是否等于num[i-1],相等则已经查找过了,就进行下一次循环
if(i>0&&nums[i]==nums[i-1]) continue;
//现在nums[i]已经大于0,后面也不会有结果
if(nums[i]>0) break;
for(int j=i+1; j<nums.length-1; j++){
//nums[j-1]等于nums[j],并且不等于nums[i],说明已经查找过了,下一次循环
//这样两次判断,加上nums从小到大排序了,所以确定了三个元素中前两个不会重复,即查找的结果都是唯一的
if(nums[j]==nums[j-1]&&j!=i+1) continue;
//每次j循环,k从最大递减,直到三个数相加小于等于0,再判断是否为0,之后的数不用比较了
int k=nums.length-1;
while(nums[i]+nums[j]+nums[k] > 0 && k>j+1){
k--;
}
if(nums[i]+nums[j]+nums[k] == 0){
subList.clear();
subList.add(nums[i]);
subList.add(nums[j]);
subList.add(nums[k]);
//注意新建list存入,不然最后全部是一样的
result.add(new ArrayList<Integer>(subList));
}
}
}
return result;
}
}