思路:
● 我们可以先遍历确定其中一个数,剩下的两个数就转化成两数之和问题 -a=b+c(target为-c)
● 分析可以得到:若三个数均为正数,必不可能和为0
● 若当前数和前一个数相同,那么这两个数的两数之和也必然相同(因为排序后的数组是单调递增的)
● 同理在双指针寻找两数之和时也是利用上面这点去重的(避免在[0,0,0,0]里找两数之和为0时出现重复)
(当然,也可以Set进行去重,因为List集合的判重方法equals ,是通过比较list中的值来判断两个list是否相同)
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> ans=new LinkedList();
Arrays.sort(nums);
for(int i=0;i<nums.length;i++){
// i数是固定不变的, 转化成两数之和,去重操作: 找到的当前数必须和上次的数不同
if(nums[i]>0)break;
if(i>0&&nums[i]==nums[i-1]) continue;
int l=i+1,r=nums.length-1;
int temp=(-1)*nums[i]; // 两数之和的结果
// 排序后的数组有序,在剩下的区间中找两数之和,若上一个数和当前数相同,这两个数的两数之和必然也相同(相同的子区间)
while(l<r&&l<nums.length&&r>=0){
int temp2=nums[l]+nums[r];
if(temp2==temp){//直接返回
// 保证了有序,数组排列,从左往右取
List<Integer> list =Arrays.asList(nums[i],nums[l],nums[r]);
ans.add(list);
// do{
// l++;
// }while(l<nums.length&&nums[l]==nums[l-1]);
l++;// 先加一成为下个个数,再减一回来和当前数比较
while(l<nums.length&&nums[l]==nums[l-1]){//和前一个数相同也返回
l++;
}
// l++;// 找到后继续往右取
}else if(temp2<temp){
l++;
}else{
r--;
}
}
}
return ans;
}
}