四数之和
class Solution {
public List<List<Integer>> fourSum(int[] nums, int target) {
int n = nums.length;
//结果
List<List<Integer>> ans = new ArrayList<List<Integer>>();
//得先进行排序,才有后面的剪枝操作
Arrays.sort(nums);
//给出的条件没有说 length >= 4,所以必须作一个约束
if (nums == null || nums.length < 4)
return ans;
for (int i = 0; i < n - 3; i ++) {
//排除重复的list
if (i > 0 && nums[i] == nums[i - 1])
continue;
//最小的四个数都大于target
//可能会超出int范围,导致判断出错,所以要用long
if ((long)nums[i] + nums[i + 1] + nums[i + 2] + nums[i + 3] > target)
break;
//说明当前的nums[i]不够大,得继续往后找,但是当前的i已经不满足,所以跳过当前的一次循环
if ((long)nums[i] + nums[n - 1] + nums[n - 2] + nums[n - 3] < target) {
continue;
}
for (int j = i + 1; j < n - 2; j ++) {
//剪枝
if (j > i + 1 && nums[j] == nums[j - 1])
continue;
if ((long)nums[i] + nums[j] + nums[j + 1] + nums[j + 2] > target)
break;
if ((long)nums[i] + nums[j] + nums[n - 1] + nums[n - 2] < target)
continue;
int pre = j + 1, last = n - 1;
while (pre < last) {
//因为这时候经过剪枝之后,目前情况的数不会超过target
//后续如果四数之和会超过target,也不至于超出范围
int sum = nums[i] + nums[j] + nums[pre] + nums[last];
if (sum == target) {
ans.add(Arrays.asList(nums[i], nums[j], nums[pre], nums[last]));
//剪枝
while (pre < last && nums[pre] == nums[pre +1])
pre ++;
pre ++;
while (pre < last && nums[last] == nums[last - 1])
last --;
last --;
}
else if (sum < target)
pre ++;
else
last --;
}
}
}
return ans;
}
}