3Sum
Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.
Note:
- Elements in a triplet (a,b,c) must be in non-descending order. (ie, a ≤ b ≤ c)
- The solution set must not contain duplicate triplets.
For example, given array S = {-1 0 1 2 -1 -4}, A solution set is: (-1, 0, 1) (-1, -1, 2)
Naive Way:这已经是我第三次做这道题了。 brute force是O(n^3),然后较好的做法是O(n^2)。
经查证,还没有方法能在小于O(n^2)的时间内解决3sum问题。实际在OJ上做,发现即使是同样的O(n^2)
的run time, 也会有超时。
第一种做法, 一开始不排序,先用一个map记录每个数的出现次数,遍历O(n^2)求两两之和,再再map中
看看有没有剩下的那个数,这样的做法需要在形成list的时候排序,并且得有一个set控制duplicate。
但是这样的做法超时了。
public class Solution { public List<List<Integer>> threeSum(int[] num) { Set<List<Integer>> set = new HashSet<List<Integer>>(); Map<Integer, Integer> map = new HashMap<Integer, Integer>(); List<List<Integer>> output = new ArrayList<List<Integer>>(); for(int i = 0;i < num.length;i++){ if(map.containsKey(num[i])) map.put(num[i], map.get(num[i])+1); else map.put(num[i], 1); } for(int i = 0;i < num.length-1;i++){ for(int j = i+1;j < num.length;j++){ int a = num[i]; int b = num[j]; int c = -num[i]-num[j]; if(map.containsKey(c)){ int count = 1; count += a==c?1:0; count += b==c?1:0; if(count <= map.get(c)){ List<Integer> list = new ArrayList<Integer>(); int arr[] = new int[3]; arr[0] = a; arr[1] = b; arr[2] = c; Arrays.sort(arr); list.add(arr[0]); list.add(arr[1]); list.add(arr[2]); if(!set.contains(list)) set.add(list); } } } } output.addAll(set); return output; } }
Improved Way: 第二种做法,也是比较牛一点的做法,就是wiki上给的做法,但是这里要求去除重复,要做出修改。
public class Solution {
public List<List<Integer>> threeSum(int[] num) {
List<List<Integer>> rlst = new ArrayList<List<Integer>>();
Arrays.sort(num);
for(int u = 0;u < num.length-2;u++){
if(u==0 || (u > 0 && num[u]!=num[u-1])){
int i = u+1;
int j = num.length-1;
while(i < j){
int sum = num[i]+num[j]+num[u];
if(sum==0){
List<Integer> list = new ArrayList<Integer>();
list.add(num[u]);
list.add(num[i]);
list.add(num[j]);
rlst.add(list);
while(i < j){
if(num[j]!=num[j-1])
break;
j--;
}
while(i < j){
if(num[i]!=num[i+1])
break;
i++;
}
i++;
j--;
}else if(sum > 0){
j--;
}else{
i++;
}
}
}
}
return rlst;
}
}
最后我发现我第一次的做法,是可以通过的O(n^2)非常非常的厉害,我觉得,居然想到了用正数负数。
public class Solution {
List<List<Integer>> output;
HashSet<List<Integer>> visited;
public List<List<Integer>> threeSum(int[] num) {
output = new ArrayList<List<Integer>>();
visited = new HashSet<List<Integer>>();
//Arrays.sort(num);
Map<Integer, Integer> positive = new HashMap<Integer, Integer>();
Map<Integer, Integer> negative = new HashMap<Integer, Integer>();
int numOfZeros = 0;
// construct the mapping
for(int i = 0;i < num.length;i++){
if(num[i] == 0)
numOfZeros++;
if(num[i] > 0)
if(positive.containsKey(num[i]))
positive.put(num[i], positive.get(num[i])+1);
else
positive.put(num[i],1);
if(num[i] < 0)
if(negative.containsKey(num[i]))
negative.put(num[i], negative.get(num[i])+1);
else
negative.put(num[i],1);
}
// generate results
// two positive + one negative
for(Map.Entry<Integer, Integer> a:positive.entrySet())
for(Map.Entry<Integer, Integer> b:positive.entrySet())
if(a.getKey() != b.getKey() || a.getValue() >= 2)
if(negative.containsKey(-a.getKey()-b.getKey()))
addResult(a.getKey(),b.getKey(),-a.getKey()-b.getKey());
// two negative + one positive
for(Map.Entry<Integer, Integer> a:negative.entrySet())
for(Map.Entry<Integer, Integer> b:negative.entrySet())
if(a.getKey() != b.getKey() || a.getValue() >= 2)
if(positive.containsKey(-a.getKey()-b.getKey()))
addResult(a.getKey(),b.getKey(),-a.getKey()-b.getKey());
// one positive+zero+one negative
if(numOfZeros > 0)
for(Map.Entry<Integer, Integer> a:negative.entrySet())
if(positive.containsKey(-a.getKey()))
addResult(0,a.getKey(),-a.getKey());
// three zeros
if(numOfZeros > 2)
addResult(0,0,0);
return output;
}
private void addResult(int a, int b, int c){
int array[] = {a,b,c};
Arrays.sort(array);
List<Integer> result = new ArrayList<Integer>();
result.add(array[0]);
result.add(array[1]);
result.add(array[2]);
if(!visited.contains(result)){
visited.add(result);
output.add(result);
}
}
}
No comments:
Post a Comment