本题使用双指针解法,代码如下
class Solution {
public List<List<Integer>> fourSum(int[] nums, int target) {
List<List<Integer>> res = new ArrayList<>();
Arrays.sort(nums);
for (int i = 0; i < nums.length; i++) {
if(nums[i] > target && target > 0) return res;
if(i > 0 && nums[i] == nums[i - 1]) continue;
for (int j = i + 1; j < nums.length; j++) {
if (nums[i] + nums[j] > target && target > 0) break;
if (j > i + 1 && nums[j] == nums[j - 1]) continue;
int l = j + 1, r = nums.length - 1;
while (l < r) {
long sum = (long) nums[i] + nums[j] + nums[l] + nums[r];
if (sum > target) {
r --;
}else if (sum < target) {
l ++;
}else {
res.add(Arrays.asList(nums[i], nums[j], nums[l], nums[r]));
while (r > l && nums[r] == nums[r - 1]) r--;
while (r > l && nums[l] == nums[l + 1]) l++;
r --;
l ++;
}
}
}
}
return res;
}
}
先将nums数组排序后遍历,其中需要注意如下几点
-
for.i循环中判断是否跳出循环的条件: nums[i] > target && target > 0,因为存在负数可能(如: -5, -4, -3 , -2, -1, 0; target = -8,-5 > -8,但实际上是存在满足可能的),所以target必须大于0时才能判断
-
for.j循环中跳出循环使用break: 在遍历过程中有可能存在i, j指针中间存在满足条件的元素,但如果return res,会直接跳过该答案,如图:
.
当前nums[i] + nums[j] > target,但红色部分存在元素满足target,所以必须使用break跳出循环,而不是return返回res数组 -
r, l的去重,r 与 r - 1对比,因为当r = nums.length - 1时,为最右端元素,需要向左去重遍历,l同理向右遍历
-
注意去重之后r, l分别需要前进一位,因为当前r, l所指向的是最后一个重复元素,且该元素已经被添加到res中,所以需要再向前进一位