这个题目的通常思路是三重循环,这种通常做法有一个地方需要注意就是先排序,然后才好去重,不然去重毫无头绪。自己可以说很缺乏这种概念了,居然没想到。
这种排序去重的想法是这样的:排序之后一样的数字就在一起了,就可以用类似于nums[i-1]==nums[i]判断了。我原来的思路是用hashset去重,可是这样直接去重是不行的,举个反例,[1,1,-2]就被排除了,也就是说这样的去重方法确实去重了,但是也不允许一个可能满足题意的序列里存在相同数字这种情况了。
双指针法比较简单一个指针指向头,一个指向尾,不断向中心靠拢,临界是二者不可相等。具体看代码就行了。
这种方法主要思想是:先排序,然后用一个for遍历数组,每次选定一个值然后用双指针法找另外两个值,如果两个指针指向的两个数之和大于当前值的相反数就减小尾部指针,反之增加头部指针。这样可以降低时间复杂度。
这种方法的精髓就是:排序—>去重——>双指针。
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
int count=0;
List<List<Integer>> list=new ArrayList<List<Integer>>();
if(nums.length<3) return list;
Arrays.sort(nums);
for(int i=0;i<nums.length;i++) {
int j=i+1;
int k=nums.length-1;
if(i>0&&nums[i-1]==nums[i])
continue;
while(j<k) {
int sum=nums[j]+nums[k];
if(sum==-nums[i]) {
List<Integer> save=new ArrayList<Integer>();
save.add(nums[i]);
save.add(nums[j]);
save.add(nums[k]);
list.add(save);
while(j<k&&nums[j+1]==nums[j]) //这里的意思跳过与本次j相同的j避免不必要的判断,下同
j++;
while(j<k&&nums[k-1]==nums[k])
k--;
j++;
k--;
}else {
if(sum>-nums[i])
{
while(j<k&&nums[k-1]==nums[k])
k--;
k--;
}
else{
while(j<k&&nums[j+1]==nums[j])
j++;
j++;
}
}
}}
return list;
}
}