给定一个包含 n 个整数的数组 nums
,判断 nums
中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。
注意:答案中不可以包含重复的三元组。
例如, 给定数组 nums = [-1, 0, 1, 2, -1, -4],
满足要求的三元组集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]
class Solution3 {
public List<List<Integer>> threeSum(int[] nums) {
List<Integer> a = new ArrayList<Integer>();
List<List<Integer>> b = new ArrayList<List<Integer>>();
Arrays.sort(nums);
for(int i=0;i<nums.length;i++) {
int target = 0-nums[i];
if(i>1 && nums[i]==nums[i-1])
continue;
int k =i+1;
int l=nums.length-1;
while(k<l) {
int xx=nums[k]+ nums[l];
if( xx == target) {
a.add(nums[i]);
a.add(nums[k]);
a.add(nums[l]);
b.add(new ArrayList<Integer>(a)); // 此处如果b.add(a) 则 a clear后,b中的a也没了
a.clear();
k=k+1;
} else if(xx < target) {
k=k+1;
} else if( xx >target) {
l=l-1;
}
}
}
// 通过hashset 去除重复
HashSet h = new HashSet(b);
b.clear();
b.addAll(h);
return b;
}
}
基本思想
先把 nums数组从小到大排序,最左端最小,最右端最大 。
从左 到右 从固定 一个数,然后把target 定位其 相反数, 然后 再找 两个数的和等于 target 即可。
【a0,a1,a2,a3,a4,a5,a6,a7】
先 令 target =a0;
然后 int k ,l 分别指向 a1,a7
第一次 while(k<l)
如果 a1+a7==target ,就加到 b 中 ,然后 k+1 指向 a2
如果 a1+a7<target ,那么 最大的a7 都不能 满足,说明没有能 数 与a1之和能等于target, 则 直接 k+1 ,指向a2
如果 a1+a7>target , 则 l-1,指向 a6 ,继续 while(k<l) 循环
第二次while(k>l)
如果 a1+a6==target .............
如果 a1+a6<target ,因为 a1+a7>target ,而a1+ a6<target ,说明没有能 数 与a1之和能等于target, 则 直接 k+1 ,指向a2
如果 a1+a6>target .............
再令 target = a1;
l 指向 a7 ,但是
注意 此时 不用 再次 把 k 指向 a0、a2、a3、a4..... ,直接 从 指向 a2 即可,因为 如果指向 a0 ,即 通过 l 向左遍历 寻找一个数,使得 a0+a(?) == - a1 也就是 a1+a(?) == -a0 ,与第一次 令target=a0 重复,所以直接 把 k指向当前target 的下一个数 ,即代码的第11行