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: 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] ]
理解题目很简单,就是挑出所有四个数字的组合,这四个数字等于target就行,这个问题关键就是遍历原始数组……
说到遍历,第一反应就是先把原数组的四个数字的组个都拿出来,然后再看那个符合要求,但是这样的做法估计在时间复杂度这关就过不了,就算出所有的组合就已经很费时间了。所以得另想办法……
如果是三个数字的话,貌似简单了许多,还有一点就是题目中没有说我们不可以改变原始数组,所以我们可以对这个数组稍稍排个序,这又大大简化了我们的问题,因为排序以后加和调整的方向是确定的,直接看代码吧,这样容易理解一些。
三个数字:
public class ThreeSum {
/**
* @param nums
* @return
*/
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> list = new ArrayList<>();
List<Integer> numsList = new ArrayList<>();
for (int i = 0; i < nums.length; i++)
numsList.add(nums[i]);
Collections.sort(numsList);
int len = numsList.size();
for (int i = 0; i < len - 2; i++){
if (i > 0 && numsList.get(i - 1).equals(numsList.get(i)))
continue;
Integer a = numsList.get(i);
int low = i + 1;
int high = len - 1;
while (low < high){
Integer b = numsList.get(low);
Integer c = numsList.get(high);
if ((a + b + c) == 0){
List<Integer> tl = new ArrayList<>();
tl.add(a);
tl.add(b);
tl.add(c);
list.add(tl);
while (low < len - 1 && numsList.get(low).equals(numsList.get(low + 1)))
low++;
while (high > 0 && numsList.get(high).equals(numsList.get(high - 1)))
high--;
low++;
high--;
}else if ((a + b + c) > 0){
while (high > 0 && numsList.get(high).equals(numsList.get(high - 1)))
high--;
high--;
}else{
while (low < len - 1 && numsList.get(low).equals(numsList.get(low + 1)))
low++;
low++;
}
}
}
return list;
}
}
上面的实现还是比较好理解的,首先呢对数组进行排序,排序的目的显而易见,就是为了方便调整,三个数字分别为a,b,c。a就是从数组开头开始遍历,b,c一个放在a的下一个位置,一个放在数组的最后一个位置,如果当前三个家伙的值跟target相等,那就啥也不说了了,直接添加,如果大于或者小于,那就得调整啦,具体咋调整代码写的很清楚,这里就不罗嗦啦……
那么现在回头再看这个问题,会发现无非就是在三个的基础上再加一个数字变成四个,那行,还是上面的思路,无非就是两层循环么,代码相似度很大,于是有了下面的实现:
代码如下:
public class FourSum {
public List<List<Integer>> fourSum(int[] nums, int target) {
List<List<Integer>> result = new ArrayList<>();
List<Integer> integerList = new ArrayList<>();
for (int num : nums) {
integerList.add(num);
}
Collections.sort(integerList);
int len = integerList.size();
for (int i = 0; i < len - 3; i++) {
if (i > 0 && integerList.get(i).equals(integerList.get(i - 1)))
continue;
Integer a = integerList.get(i);
Integer rest = (Integer) target - a;
for (int j = i + 1; j < len - 2; j++) {
if (j > i + 1 && integerList.get(j - 1).equals(integerList.get(j)))
continue;
Integer b = integerList.get(j);
int low = j + 1;
int high = len - 1;
while (low < high) {
Integer c = integerList.get(low);
Integer d = integerList.get(high);
if (rest - (b + c + d) == 0) {
List<Integer> tl = new ArrayList<>();
tl.add(a);
tl.add(b);
tl.add(c);
tl.add(d);
result.add(tl);
while (low < len - 1 && integerList.get(low).equals(integerList.get(low + 1)))
low++;
while (high > j + 1 && integerList.get(high).equals(integerList.get(high - 1)))
high--;
low++;
high--;
} else if (rest - (b + c + d) > 0) {
while (low < len - 1 && integerList.get(low).equals(integerList.get(low + 1)))
low++;
low++;
} else {
while (high > j + 1 && integerList.get(high).equals(integerList.get(high - 1)))
high--;
high--;
}
}
}
}
return result;
}
}
实话讲,这个代码的时间复杂度还是有些高,如果字符串变态些还是怕扛不住……后面有好办法再跟新吧