我看了几个人气比较高的博客,他们这个算法都没做到O(n^2),所以提前将我的解法贴出来分享,供大家参考(前面略过的题目近期都会补上的)。
【题目】:
Given an array S of n integers, are there elements a, b, c, and d in S such that a + b + c + d = target? Find all unique quadruplets in the array which gives the sum of target.
Note:
Elements in a quadruplet (a,b,c,d) must be in non-descending order. (ie, a ≤ b ≤ c ≤ d)
The solution set must not contain duplicate quadruplets.
For example, given array S = {1 0 -1 0 -2 2}, and target = 0.
A solution set is:
(-1, 0, 0, 1)
(-2, -1, 1, 2)
(-2, 0, 0, 2)
Tags: Array Hash Table Two Pointers
【解析】 我写代码的时候把思路写在了代码注释里了,请直接往下看:
【上码】
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.List;
import java.util.Vector;
/*
* 参考:未参考他人算法
* O(n^2)
* 思路:先将每对数塞进一个Hashtable(以这对数的和为key,以一个包含所有和为key的数对的集合为value)。
* 然后遍历该Hashtable,对于每个和为key的数对集合,在该Hashtable中get和为target-key的数对集合,
* 如果get到的为空,则continue,如果get到的不为空,则将这两个数对和并为一个有序4元组,并查看是否之前该
* 4元组是否已经出现过(用另一个Hastable<String,AnyType>:reappear来快速判断,该reappear的
* key是用有序4元组的4个整数拼接而来的)。 如果该4元组为出现过,则将其加入到结果集合里。
*
*/
public class Solution1 {
public List<List<Integer>> fourSum(int[] num, int target) {
List<List<Integer>> list = new ArrayList<List<Integer>>();
if (num == null || num.length < 4)
return list;
int len = num.length;
Hashtable<Integer,PairRecoder> prs = new Hashtable<Integer,PairRecoder>(len*len);
for (int i = 0; i < len - 1; i++) {
for (int j = i + 1; j < len; j++) {
int sum = num[i]+num[j];
PairRecoder pr = prs.get(num[i]+num[j]);
if(pr == null)
prs.put(sum, new PairRecoder(sum,i,j));
else
pr.pairs.add(new Pair(i,j));
}
}
List<Four> fours = new ArrayList<Four>();
Hashtable<String,Boolean> reappear = new Hashtable<String,Boolean>();
for(Enumeration<PairRecoder> e=prs.elements(); e.hasMoreElements(); ){
PairRecoder pr1 = (PairRecoder)e.nextElement();
PairRecoder pr2 = prs.get(target-pr1.v);
if(pr2 == null)
continue;
for(int i=0;i<pr1.pairs.size();i++)
for(int j=0;j<pr2.pairs.size();j++){
Pair p1 = pr1.pairs.elementAt(i);
Pair p2 = pr2.pairs.elementAt(j);
if(p1.v1!=p2.v1 &&p1.v1!=p2.v2 && p1.v2!=p2.v1 && p1.v2!=p2.v2){
Four of = new OrderedFour(num[p1.v1],num[p1.v2],num[p2.v1],num[p2.v2]);
StringBuffer sb = new StringBuffer();
sb.append(of.num.get(0));
sb.append(of.num.get(1));
sb.append(of.num.get(2));
sb.append(of.num.get(3));
if(!reappear.containsKey(sb.toString())){
list.add(of.num);
System.out.println("new:"+sb);
reappear.put(sb.toString(),true);
}
}
}
}
return list;
}
class Pair {
int v1;
int v2;
Pair(int v1, int v2) {
this.v1 = v1;
this.v2 = v2;
}
}
class PairRecoder{
int v;
Vector<Pair> pairs = new Vector<Pair>();
PairRecoder(int v,int i,int j){
this.v = v;
this.pairs.add(new Pair(i,j));
}
}
class Four{
List<Integer> num;
Four(int v1,int v2,int v3,int v4){
this.num = new ArrayList<Integer>();
num.add(v1);
num.add(v2);
num.add(v3);
num.add(v4);
}
}
class OrderedFour extends Four{
OrderedFour(int v1,int v2,int v3,int v4) {
super(v1, v2, v3, v4);
Collections.sort(this.num);
}
}
}