四数之和
给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] (若两个四元组元素一一对应,则认为两个四元组重复):
0 <= a, b, c, d < n
a、b、c 和 d 互不相同
nums[a] + nums[b] + nums[c] + nums[d] == target
你可以按任意顺序返回答案 。
思路:本题一看就是三数之和的变体,仍可使用双指针两边夹逼,然后外层用双循环来确定另两元素,按此思路编写代码如下:
class Solution {
public List<List<Integer>> fourSum(int[] nums, int target) {
int length = nums.length;
List<List<Integer>> res = new ArrayList<>();
Arrays.sort(nums);
for (int i = 0; i < length - 3; i++) {
for (int j = i + 1; j < length - 2; j++) {
int k = j + 1;
int l = length - 1;
while (k < l) {
int sum = nums[i] + nums[j] + nums[k] +nums[l];
if (sum == target) {
//写入容器
res.add(new ArrayList<Integer>(Arrays.asList(nums[i], nums[j], nums[k], nums[l])));
break;
} else if (sum < target) {
while (k < l && nums[k] == nums[++k]);
} else {
while (k < l && nums[l] == nums[--l]);
}
}
}
}
return res;
}
}
=========================================================================
但是提交没能通过,看到问题立马就想到了,这是因为没做去重的缘故,而且去重则正是本题的难点,因为有两个元素是靠循环来确定的,所以存在逆序的问题,即1,2和2,1应该被视为重复,此时循环应该continue掉,为此需要维持一个长度为2的数组,记录i,j元素的数值,笔者想到了一个比较两元素是否为逆序的思路,利用两数之和与两数之差的绝对值来判断。
class Solution {
public List<List<Integer>> fourSum(int[] nums, int target) {
int length = nums.length;
List<List<Integer>> res = new ArrayList<>();
int[] tempNums = new int[2];
boolean init = true;
Arrays.sort(nums);
for (int i = 0; i < length - 3; i++) {
for (int j = i + 1; j < length - 2; j++) {
if (init) {
tempNums[0] = nums[i];
tempNums[1] = nums[j];
init = false;
}
//去重
if (Math.abs(tempNums[0] - tempNums[1]) == Math.abs(nums[i] - nums[j]) &&
nums[i] + nums[j] == tempNums[0] + tempNums[1]) {
continue;
}
else {
tempNums[0] = nums[i];
tempNums[1] = nums[j];
}
int k = j + 1;
int l = length - 1;
while (k < l) {
int sum = nums[i] + nums[j] + nums[k] +nums[l];
if (sum == target) {
//写入容器
res.add(new ArrayList<Integer>(Arrays.asList(nums[i], nums[j], nums[k], nums[l])));
break;
} else if (sum < target) {
while (k < l && nums[k] == nums[++k]);
k++;
} else {
while (k < l && nums[l] == nums[--l]);
}
}
}
}
return res;
}
}
=========================================================================运行了一下,还是有问题,还是看看答案吧!
class Solution {
public List<List<Integer>> fourSum(int[] nums, int target) {
List<List<Integer>> result = new ArrayList<>();
Arrays.sort(nums);
for (int i = 0; i < nums.length; i++) {
if (nums[i] > 0 && nums[i] > target) {
return result;
}
if (i > 0 && nums[i - 1] == nums[i]) {
continue;
}
for (int j = i + 1; j < nums.length; j++) {
if (j > i + 1 && nums[j - 1] == nums[j]) {
continue;
}
int left = j + 1;
int right = nums.length - 1;
while (right > left) {
long sum = (long) nums[i] + nums[j] + nums[left] + nums[right];
if (sum > target) {
right--;
} else if (sum < target) {
left++;
} else {
result.add(Arrays.asList(nums[i], nums[j], nums[left], nums[right]));
while (right > left && nums[right] == nums[right - 1]) right--;
while (right > left && nums[left] == nums[left + 1]) left++;
left++;
right--;
}
}
}
}
return result;
}
}