給定一個包含 n 個整數的數組 nums 和一個目標值 target,判斷 nums 中是否存在四個元素 a,b,c 和 d ,使得 a +
b + c + d 的值與 target 相等?找出所有滿足條件且不重複的四元組。注意:
答案中不可以包含重複的四元組。
示例:
給定數組 nums = [1, 0, -1, 0, -2, 2],和 target = 0。
滿足要求的四元組集合爲: [ [-1, 0, 0, 1], [-2, -1, 1, 2], [-2, 0, 0, 2] ]
static List<List<Integer>> lists;
public static List<List<Integer>> fourSum(int[] nums, int target) {
if (nums.length < 4) {
return new ArrayList<List<Integer>>();
}
//先做排序,方便後面判斷
Arrays.sort(nums);
lists = new ArrayList<List<Integer>>();
for (int i = 0; i < nums.length - 3; i++) {
//第一個數字,如果發現跟前面數字相等可以直接忽略,因爲沒有任何情況還會符合要求,只可能跟前面的可能性重複
//也不必擔心有相同數字組成目標解得情況,這個也在前面的循環會遍歷到
if (i > 0 && nums[i] == nums[i - 1]) {
continue;
}
for (int j = i + 1; j < nums.length - 2; j++) {
//第二個數字,也是跟前一數字相等時可以忽略
if (j > i + 1 && nums[j] == nums[j - 1]) {
continue;
}
int res = target - nums[i] - nums[j];
//當i,j確定時算一下當前最大最小值
int maxV = nums[nums.length - 2] + nums[nums.length - 1];
int minV = nums[j + 1] + nums[j + 2];
//如果當前最小值都大於目標值或者當前最大值都小於目標值就不必再往下走了
if (maxV <= res || minV >= res) {
if (maxV == res) {
//如果當前最大值等於target,那這一輪只有這一個符合要求
//添加到list中
List<Integer> temp = new ArrayList<Integer>();
temp.add(nums[i]);
temp.add(nums[j]);
temp.add(nums[nums.length - 2]);
temp.add(nums[nums.length - 1]);
lists.add(temp);
} else if (minV == res) {
//只有當前最小值符合要求
//添加到list中
List<Integer> temp = new ArrayList<Integer>();
temp.add(nums[i]);
temp.add(nums[j]);
temp.add(nums[j + 1]);
temp.add(nums[j + 2]);
lists.add(temp);
}
continue;
}
//從兩端往中間夾逼
int left = j + 1;
int right = nums.length - 1;
while (left < right) {
if (nums[left] + nums[right] > res) {
//大於目標值,右端左移
right--;
while (left < right) {
//對數字相同情況的判斷
if (nums[right] == nums[right + 1]) {
right--;
} else {
break;
}
}
} else if (nums[left] + nums[right] < res) {
//小於目標值,左端右移
left++;
while (left < right) {
//對數字相同情況的判斷
if (nums[left] == nums[left - 1]) {
left++;
} else {
break;
}
}
} else {
//添加到list中
List<Integer> temp = new ArrayList<Integer>();
temp.add(nums[i]);
temp.add(nums[j]);
temp.add(nums[left]);
temp.add(nums[right]);
lists.add(temp);
//這裏要考慮到下一元素和當前元素有可能相等,爲避免重複要進行判斷
left++;
while (left < right) {
if (nums[left] == nums[left - 1]) {
left++;
} else {
break;
}
}
right--;
while (left < right) {
if (nums[right] == nums[right + 1]) {
right--;
} else {
break;
}
}
}
}
}
}
return lists;
}