题目:
给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。
注意:答案中不可以包含重复的三元组。
例如, 给定数组 nums = [-1, 0, 1, 2, -1, -4],
满足要求的三元组集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]
题解1: 排序+哈希表
先把数组排序,然后选定两个数字之后去HashMap里找另一个数字,但是我写的比较繁琐,应该可以进行进一步优化,Time complexity理想状况下为O(N)
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
//先用Arrays.sort()排序 ---> [-4,-1,-1,0,1,2]
//记录下负数的个数,把所有数字都存入HashMap里
//1.双层for循环求和负数,然后去HashMap里找对应的正数
//2.判断是否有0,如果有0则挨个寻找相反的数
List<List<Integer>> list = new ArrayList<>();
if(nums.length < 3) return list;
Arrays.sort(nums);
int negative = 0;
int positive = 0;
int zero = 0;
int sum = 0;
HashMap<Integer, Integer> map = new HashMap<>();
for(int i=0; i<nums.length; i++){
if(nums[i] < 0) {
negative++;
}else if(nums[i] == 0) {
zero++;
}else{
positive++;
}
map.put(nums[i], 1);
}
if(negative >= 2){
for(int i=0; i<negative-1; i++){
if((i>0 && nums[i]==nums[i-1])) continue;
for(int j=i+1; j<negative; j++){
if(j>i+1 && nums[j]==nums[j-1]) continue;
sum = -1*(nums[i] + nums[j]);
// System.out.println(sum);
if(map.containsKey(sum)){
// System.out.println(sum);
List<Integer> sub = new ArrayList<>();
sub.add(nums[i]);
sub.add(nums[j]);
sub.add(sum);
list.add(sub);
}
}
}
}
if(positive>=2){
for(int i=nums.length-positive; i<nums.length; i++){
if(i>0 && nums[i]==nums[i-1]) continue;
for(int j=i+1; j<nums.length; j++){
if(j>i+1 && nums[j]==nums[j-1]) continue;
sum = -1*(nums[i] + nums[j]);
if(map.containsKey(sum)){
List<Integer> sub = new ArrayList<>();
sub.add(nums[i]);
sub.add(nums[j]);
sub.add(sum);
list.add(sub);
}
}
}
}
// System.out.println(1);
if(zero > 0){
if(zero >= 3){
List<Integer> sub = new ArrayList<>();
sub.add(0);
sub.add(0);
sub.add(0);
list.add(sub);
}
for(int i=0; i<negative; i++){
if(i>0 && nums[i]==nums[i-1]){
continue;
}
if(map.containsKey(-1*nums[i])){
List<Integer> sub = new ArrayList<>();
sub.add(0);
sub.add(nums[i]);
sub.add(-1*nums[i]);
list.add(sub);
}
}
}
return list;
}
}
题解2: 排序+对撞指针
先排序,for loop循环拿到第一个数,然后用对撞指针找到另外两个数字,相当于for loop做2Sum
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
Arrays.sort(nums);
int n = nums.length;
List<List<Integer>> res = new LinkedList<>();
for (int i = 0; i < n; i++) {
if (i > 0 && nums[i] == nums[i - 1]) continue;
int left = i + 1;
int right = n - 1;
while (left < right) {
int tmp = nums[i] + nums[left] + nums[right];
if (tmp == 0) {
res.add(Arrays.asList(nums[i], nums[left], nums[right]));
while (left < right && nums[left] == nums[left + 1]) left += 1;
while (left < right && nums[right] == nums[right - 1]) right -= 1;
left += 1;
right -= 1;
} else if (tmp > 0) right -= 1;
else left += 1;
}
}
return res;
}
}