题目描述
解法
第一次:
利用三元组组成的整数范围属于-999到999来判断重复,使用一个标记数组register即可。
然后对每个数,我们只需要找到两个数的和为0-该数即可。
进而转化为两数之和的问题。
两数之和,我们知道有双指针的解法,或者查一次哈希表的方法,但是哈希表可以建立在无序数组。双指针只能建立在有序的数组上。
第一次我傻了,竟然使用哈希表:
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;
import java.util.Arrays;
public class Solution {
public ArrayList<ArrayList<Integer>> threeSum(int[] num) {
ArrayList<ArrayList<Integer>> result = new ArrayList<>();
//对数组排序先
Arrays.sort(num);//升序
//然后利用数组标记是否重复
boolean[] register = new boolean[2000];
if(num==null ||num.length<3) return result;
Map<Integer,Integer> map = new HashMap<>();
int pre = 0;//上一个插入数据的最左边的坐标
for(int i=0;i<num.length;i++){
int target = 0-num[i];
for(int j=i+1;j<num.length;j++){
if(map.containsKey(target-num[j])){
//找到了一组
int k = (int)map.get(target-num[j]);//j必然大于k
int index;
if(num[i]<0){
index = (int)(Math.abs(num[i])*100+ Math.abs(num[j])*10+Math.abs(num[k]));
if(register[index]==false){//没有加入过
ArrayList<Integer> one = new ArrayList<>();
one.add(num[i]);
one.add(num[k]);
one.add(num[j]);
result.add(one);
register[index]=true;//标记
}
}else{
index = (int)(Math.abs(num[i])*100+ Math.abs(num[j])*10+Math.abs(num[k])+1000);//正数需要映射
if(register[index]==false){//没有加入过
ArrayList<Integer> one = new ArrayList<>();
one.add(num[i]);
one.add(num[k]);
one.add(num[j]);
result.add(one);
register[index]=true;
}
}
}else{
map.put(num[j],j);
}
}
map.clear();//重新记录
}
//它要按照遍历的坐标顺序添加进去。。。所以还要改
return result;
}
}
它要求加入的顺序必须符合它的评判,谁在前谁先添加。所以使用双指针了。
第二次:
严格遵循labuladong里面所说的二分查找注意,可以很快写出如下代码:
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;
import java.util.Arrays;
public class Solution {
public ArrayList<ArrayList<Integer>> threeSum(int[] num) {
ArrayList<ArrayList<Integer>> result = new ArrayList<>();
//对数组排序先
Arrays.sort(num);//升序
//然后利用数组标记是否重复
boolean[] register = new boolean[2000];
if(num==null ||num.length<3) return result;
for(int i=0;i<num.length;i++){
int target = 0-num[i];
//利用双指针:
int left = i+1,right = num.length-1;
while(left<right){//[left,right)
if(num[left]+num[right]>target){//变小
right--;
}else if(num[left]+num[right]<target){
left++;
}else if(num[left]+num[right]==target){
//判断重复性:
int index;
if(num[i]<0){
index = (int)(Math.abs(num[i])*100+ Math.abs(num[left])*10+Math.abs(num[right]));
if(register[index]==false){//没有加入过
ArrayList<Integer> one = new ArrayList<>();
one.add(num[i]);
one.add(num[left]);
one.add(num[right]);
result.add(one);
register[index]=true;//标记
}
}else{
index = (int)(Math.abs(num[i])*100+ Math.abs(num[left])*10+Math.abs(num[right])+1000);//正数需要映射
if(register[index]==false){//没有加入过
ArrayList<Integer> one = new ArrayList<>();
one.add(num[i]);
one.add(num[left]);
one.add(num[right]);
result.add(one);
register[index]=true;
}
}
//找到一组:
left++;
}
}
}
return result;
}
}