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)
这题的难点在于面向接口编程。 那个 声明 result 的方法很考究。
1 List<List<Integer>> test = new ArrayList<List<Integer>>();
2 List<Integer> row = new ArrayList<Integer>();
3 test.add(row);
1 public class Solution { 2 public List<List<Integer>> fourSum(int[] num, int target) { 3 List<List<Integer>> result = new ArrayList<List<Integer>>(); 4 if(num == null || num.length < 4) return result; 5 Arrays.sort(num); 6 int len = num.length; 7 for(int a = 0; a < len - 3; a ++){ 8 if(a == 0 || num[a] != num[a - 1]){ 9 for(int b = a + 1; b < len - 2; b ++){ 10 if(b == a + 1 || num[b] != num[b - 1]){ 11 int c = b + 1, d = len - 1; 12 int goal = target - num[a] - num[b]; 13 while(c < d){ 14 if(num[c] + num[d] < goal) c ++; 15 else if(num[c] + num[d] > goal) d--; 16 else{ 17 ArrayList<Integer> row = new ArrayList<Integer>(); 18 row.add(num[a]); 19 row.add(num[b]); 20 row.add(num[c]); 21 row.add(num[d]); 22 result.add(row); 23 int cc = num[c], dd = num[d]; 24 while(c < d && num[c] == cc) c ++; 25 while(c < d && num[d] == dd) d --; 26 } 27 } 28 } 29 } 30 } 31 } 32 return result; 33 } 34 }
n^2 的算法:
4sum的hash算法:
O(N^2)把所有pair存入hash表,并且每个hash值下面可以跟一个list做成map, map[hashvalue] = list,每个list中的元素就是一个pair, 这个pair的和就是这个hash值,那么接下来求4sum就变成了在所有的pair value中求 2sum,这个就成了线性算法了,注意这里的线性又是针对pair数量(N^2)的线性,所以整体上这个算法是O(N^2),而且因为我们挂了list, 所以只要符合4sum的我们都可以找到对应的是哪四个数字。
1 public class Solution { 2 public List<List<Integer>> fourSum(int[] num, int target) { 3 ArrayList<List<Integer>> result = new ArrayList<List<Integer>> (); 4 if(num == null || num.length < 4) return result; 5 Arrays.sort(num); 6 HashMap<Integer, ArrayList<Integer[]>> pair = new HashMap<Integer, ArrayList<Integer[]>> (); 7 for(int i = 0; i < num.length; i ++){ 8 if(i == 0 || num[i] != num[i - 1]){ 9 for(int j = i + 1; j < num.length; j ++){ 10 if(j == i + 1 || num[j] != num[j - 1]){ 11 Integer sum = num[i] + num[j]; 12 if(pair.containsKey(sum)) pair.get(sum).add(new Integer[]{num[i], num[j]}); 13 else { 14 ArrayList<Integer[]> list = new ArrayList<Integer[]> (); 15 list.add(new Integer[]{num[i], num[j]}); 16 pair.put(sum, list); 17 } 18 } 19 } 20 } 21 } 22 23 HashMap<Integer, Integer> maxAppear = new HashMap<Integer, Integer>(); 24 for(int i = 0; i < num.length; i ++){ 25 if(maxAppear.containsKey(num[i])) maxAppear.put(num[i], maxAppear.get(num[i]) + 1); 26 else maxAppear.put(num[i], 1); 27 } 28 29 HashSet<Integer> resultSet = new HashSet<Integer>(); 30 31 Iterator point = pair.entrySet().iterator(); 32 while(point.hasNext()){ 33 Map.Entry pairs = (Map.Entry)point.next(); 34 Integer goal = target - (int)pairs.getKey(); 35 if(pair.containsKey(goal)){ 36 ArrayList<Integer[]> right = pair.get(goal); 37 ArrayList<Integer[]> left = (ArrayList<Integer[]>)pairs.getValue(); 38 for(int i = 0; i < left.size(); i ++){ 39 for(int j = 0; j < right.size(); j ++){ 40 int[] row = isValidList(left.get(i), right.get(j),new HashMap<Integer, Integer>(maxAppear)); 41 if(row != null){ 42 int rowValue = ((row[0] * 31 + row[1]) * 31 + row[2]) * 31 + row[3]; 43 if(!resultSet.contains(rowValue)){ 44 ArrayList<Integer> oneRow = new ArrayList<Integer>(); 45 oneRow.add(row[0]); 46 oneRow.add(row[1]); 47 oneRow.add(row[2]); 48 oneRow.add(row[3]); 49 result.add(oneRow); 50 resultSet.add(rowValue); 51 } 52 } 53 } 54 } 55 } 56 } 57 return result; 58 } 59 60 public int[] isValidList(Integer[] first, Integer[] second, HashMap<Integer, Integer> maxAppear){ 61 if(first[1] > second[0]) return (int[]) null; 62 int[] result = new int[4]; 63 result[0] = first[0]; 64 result[1] = first[1]; 65 result[2] = second[0]; 66 result[3] = second[1]; 67 for(int i = 0; i < 4; i ++){ 68 if(maxAppear.containsKey(result[i]) && maxAppear.get(result[i]) > 0) maxAppear.put(result[i], maxAppear.get(result[i]) - 1); 69 else return (int[]) null; 70 } 71 return result; 72 } 73 }
迭代器(Iterator)
迭代器是一种设计模式,它是一个对象,它可以遍历并选择序列中的对象,而开发人员不需要了解该序列的底层结构。迭代器通常被称为“轻量级”对象,因为创建它的代价小。
Java中的Iterator功能比较简单,并且只能单向移动:
(1) 使用方法iterator()要求容器返回一个Iterator。第一次调用Iterator的next()方法时,它返回序列的第一个元素。注意:iterator()方法是java.lang.Iterable接口,被Collection继承。
(2) 使用next()获得序列中的下一个元素。
(3) 使用hasNext()检查序列中是否还有元素。
(4) 使用remove()将迭代器新返回的元素删除。
Iterator是Java迭代器最简单的实现,为List设计的ListIterator具有更多的功能,它可以从两个方向遍历List,也可以从List中插入和删除元素。
迭代器应用:
list l = new ArrayList();
l.add("aa");
l.add("bb");
l.add("cc");
for (Iterator iter = l.iterator(); iter.hasNext();) {
String str = (String)iter.next();
System.out.println(str);
}
/*迭代器用于while循环
Iterator iter = l.iterator();
while(iter.hasNext()){
String str = (String) iter.next();
System.out.println(str);
}
*/