基础知识要求:
Java:方法、集合、泛型、if else语句、while循环、for循环、逻辑运算符、自增自减运算符、数组、Arrays.sort()、Arrays.asList()
Python: 方法、if else语句、while循环、for循环、逻辑运算符、列表
题目:
给你一个由 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
你可以按 任意顺序 返回答案 。
示例 1:
输入:nums = [1,0,-1,0,-2,2], target = 0 输出:[[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]]
示例 2:
输入:nums = [2,2,2,2,2], target = 8 输出:[[2,2,2,2]]
提示:
1 <= nums.length <= 200
-109 <= nums[i] <= 109
-109 <= target <= 109
思路解析:
-
排序:首先,我们对输入数组
nums
进行排序。排序有助于我们跳过重复的数字,并优化搜索过程。 -
固定前两个数:我们使用两个指针
i
和j
来固定前两个数。指针i
从数组的起始位置开始遍历,而指针j
则从i
的下一个位置开始遍历。由于数组已经排序,我们可以通过比较当前的和与目标值来跳过一些不必要的搜索。- 如果当前两个数之和加上剩余所有数的最小值和最大值仍然小于目标值,那么无需继续遍历当前
i
,因为后续的组合的和只会更大。 - 如果当前两个数之和已经大于目标值,那么同样无需继续向后遍历,因为后续的组合的和只会更大。
- 如果当前两个数之和加上剩余所有数的最小值和最大值仍然小于目标值,那么无需继续遍历当前
-
固定第三个数:在固定前两个数之后,我们使用指针
j
来固定第三个数。与固定前两个数类似,我们需要跳过重复的数字以避免重复的组合。 -
双指针法:在固定了前三个数之后,我们使用双指针
left
和right
来从数组的剩余部分中选择第四个数。双指针left
从j + 1
开始,而right
从数组的末尾开始。- 如果四个数的和等于目标值,我们将这个组合添加到结果列表中,并尝试跳过重复的数字以避免重复的组合。
- 如果和小于目标值,我们增加
left
指针来增大和。 - 如果和大于目标值,我们减小
right
指针来减小和。
-
跳过重复的数字:在遍历过程中,我们需要跳过重复的数字以避免产生重复的组合。这是通过在固定每个数字后检查它是否与前一个数字相同来实现的。
-
返回结果:最后,我们返回所有满足条件的四元组列表。
Java代码示例:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Solution {
public List<List<Integer>> fourSum(int[] nums, int target) {
List<List<Integer>> result = new ArrayList<>(); // 存储满足条件的四元组结果
if (nums == null || nums.length < 4) {
return result; // 如果数组为空或长度小于4,直接返回空结果
}
// 对数组进行排序,以便使用双指针法
Arrays.sort(nums);
int n = nums.length;
// 固定前两个数(i, j)
for (int i = 0; i < n - 3; i++) {
// 跳过重复的数字,避免重复组合
if (i > 0 && nums[i] == nums[i - 1]) {
continue;
}
// 如果当前4个数之和已经大于目标值,则无需继续向后遍历
if (nums[i] + nums[i + 1] + nums[i + 2] + nums[i + 3] > target) {
break;
}
// 如果当前数加上3个最大值仍然小于目标值,则无需继续遍历当前i
if (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;
}
// 双指针,从两端向中间遍历(left, right)
int left = j + 1;
int right = n - 1;
while (left < right) {
int sum = nums[i] + nums[j] + nums[left] + nums[right];
// 如果和等于目标值
if (sum == target) {
// 将当前四元组添加到结果列表中
result.add(Arrays.asList(nums[i], nums[j], nums[left], nums[right]));
// 跳过重复的数字
while (left < right && nums[left] == nums[left + 1]) {
left++;
}
while (left < right && nums[right] == nums[right - 1]) {
right--;
}
// 移动指针,继续寻找
left++;
right--;
}
// 如果和小于目标值,移动左指针
else if (sum < target) {
left++;
}
// 如果和大于目标值,移动右指针
else {
right--;
}
}
}
}
// 返回结果列表
return result;
}
// 主方法用于测试
public static void main(String[] args) {
Solution solution = new Solution();
int[] nums = {1, 0, -1, 0, -2, 2};
int target = 0;
List<List<Integer>> result = solution.fourSum(nums, target);
for (List<Integer> quadruplet : result) {
System.out.println(quadruplet);
}
}
}
Python代码示例:
from typing import List
def four_sum(nums: List[int], target: int) -> List[List[int]]:
# 初始化结果列表
result = []
# 如果数组长度小于4,直接返回空列表
if len(nums) < 4:
return result
# 对数组进行排序
nums.sort()
n = len(nums)
# 固定前两个数(i, j)
for i in range(n - 3):
# 跳过重复的数字
if i > 0 and nums[i] == nums[i - 1]:
continue
# 如果当前两个数之和已经大于目标值,则无需继续向后遍历
if nums[i] + nums[i + 1] + nums[i + 2] + nums[i + 3] > target:
break
# 如果当前两个数之和加上剩余所有数的最小值和最大值仍然小于目标值,则无需继续遍历当前i
if nums[i] + nums[n - 1] + nums[n - 2] + nums[n - 3] < target:
continue
# 固定第三个数(j)
for j in range(i + 1, n - 2):
# 跳过重复的数字
if j > i + 1 and nums[j] == nums[j - 1]:
continue
# 双指针,从两端向中间遍历(left, right)
left = j + 1
right = n - 1
while left < right:
total = nums[i] + nums[j] + nums[left] + nums[right]
# 如果四个数的和等于目标值
if total == target:
# 将当前四元组添加到结果列表中
result.append([nums[i], nums[j], nums[left], nums[right]])
# 跳过重复的数字
while left < right and nums[left] == nums[left + 1]:
left += 1
while left < right and nums[right] == nums[right - 1]:
right -= 1
# 移动指针,继续寻找
left += 1
right -= 1
# 如果和小于目标值,移动左指针
elif total < target:
left += 1
# 如果和大于目标值,移动右指针
else:
right -= 1
# 返回结果列表
return result
# 测试代码
nums = [1, 0, -1, 0, -2, 2]
target = 0
print(four_sum(nums, target))