题目:4 Sum
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)
分析:根据之前解过的三数之和,这个问题很容易归纳为写个4重循环,时间复杂度O(n^4),但遗憾的是,无论在这个基础上怎么优化,它都会超时。
如果我们只需要求两数之和呢,需要写2重循环来枚举所有可能性吗?对于一个已排序的数组,这是没有必要的。我们需要做的只是,定义两个下标,一个在最左(设为left),一个在最右(设为right):
- 如果num[left] + num[right] > target,那么应该当最右的下标左移,即right--
- 如果num[left] + num[right] < target,则应该left++
- 如果num[left] + num[right] == target,则这就是我们要找的组合了,同时left++,right--继续搜寻
上述算法时间复杂度O(n).
于是对于四数之和,我们便可能先甩出2重循环,确定前面两数,再对后面两个数采用上述算法搜索,总时间复杂度O(n^3).
代码:
public class Solution {
public ArrayList<ArrayList<Integer>> fourSum(int[] num, int target) {
ArrayList<ArrayList<Integer>> array = new ArrayList<ArrayList<Integer>>();
ArrayList<Integer> solution = null;
Arrays.sort(num);
int left, right;
int i, j , r;
int len = num.length;
if (len < 4) return array;
for (i = 0; i < len - 3; i++) {
if (i != 0 && num[i] == num[i-1]) continue;
for (j = i + 1; j < len - 2; j++) {
if (j != i + 1 && num[j] == num[j-1]) continue;
left = j + 1;
right = len - 1;
while (left < right) {
if (left != j + 1 && num[left] == num[left-1]) {
left++;
continue;
}
if (right != len - 1 && num[right] == num[right+1]) {
right--;
continue;
}
r = num[i] + num[j] + num[left] + num[right];
if (r < target) left++;
if (r > target) right--;
if (r == target) {
solution = new ArrayList<Integer>();
solution.add(num[i]);
solution.add(num[j]);
solution.add(num[left]);
solution.add(num[right]);
array.add(solution);
left++;
right--;
}
}
}
}
return array;
}
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。