四数之和
难度:
标签:
题目描述
给你一个由 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
代码结果
运行时间: 1324 ms, 内存: 15.3 MB
/*
* 思路:
* 1. 首先对数组进行排序。
* 2. 使用组合算法生成四元组,过滤掉不符合条件的四元组。
* 3. 使用Stream API的distinct()方法去除重复的四元组。
* 4. 将结果收集为List。
*/
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class FourSumStream {
public List<List<Integer>> fourSum(int[] nums, int target) {
return IntStream.range(0, nums.length)
.boxed()
.flatMap(a -> IntStream.range(a + 1, nums.length)
.boxed()
.flatMap(b -> IntStream.range(b + 1, nums.length)
.boxed()
.flatMap(c -> IntStream.range(c + 1, nums.length)
.boxed()
.filter(d -> nums[a] + nums[b] + nums[c] + nums[d] == target)
.map(d -> Arrays.asList(nums[a], nums[b], nums[c], nums[d]))
)
)
)
.distinct()
.sorted((o1, o2) -> {
for (int i = 0; i < o1.size(); i++) {
int cmp = o1.get(i) - o2.get(i);
if (cmp != 0) return cmp;
}
return 0;
})
.collect(Collectors.toList());
}
}
解释
方法:
这道题目使用了nSum的递归思想来解决。首先将数组排序,然后递归地调用nSum函数,将问题不断分解成更小的子问题,直到问题简化为两数之和。在两数之和的处理中,使用双指针技巧来寻找和为目标值的元素对。为了避免重复解,每次找到一个解后,需要跳过相同的元素。
时间复杂度:
O(n^3)
空间复杂度:
O(n^3)
代码细节讲解
🦆
为什么在两数之和的问题中选择使用双指针而不是哈希表的方法?
▷🦆
在多层递归中如何确保避免重复的四元组出现?
▷🦆
当nSum函数中的n大于2时,为什么选择将问题递减至n-1而不是更小的数?
▷相关问题
两数之和
给定一个整数数组 nums
和一个整数目标值 target
,请你在该数组中找出 和为目标值 target
的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
示例 1:
输入:nums = [2,7,11,15], target = 9 输出:[0,1] 解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
示例 2:
输入:nums = [3,2,4], target = 6 输出:[1,2]
示例 3:
输入:nums = [3,3], target = 6 输出:[0,1]
提示:
2 <= nums.length <= 104
-109 <= nums[i] <= 109
-109 <= target <= 109
- 只会存在一个有效答案
进阶:你可以想出一个时间复杂度小于 O(n2)
的算法吗?
三数之和
给你一个整数数组 nums
,判断是否存在三元组 [nums[i], nums[j], nums[k]]
满足 i != j
、i != k
且 j != k
,同时还满足 nums[i] + nums[j] + nums[k] == 0
。请
你返回所有和为 0
且不重复的三元组。
注意:答案中不可以包含重复的三元组。
示例 1:
输入:nums = [-1,0,1,2,-1,-4] 输出:[[-1,-1,2],[-1,0,1]] 解释: nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0 。 nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 。 nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。 不同的三元组是 [-1,0,1] 和 [-1,-1,2] 。 注意,输出的顺序和三元组的顺序并不重要。
示例 2:
输入:nums = [0,1,1] 输出:[] 解释:唯一可能的三元组和不为 0 。
示例 3:
输入:nums = [0,0,0] 输出:[[0,0,0]] 解释:唯一可能的三元组和为 0 。
提示:
3 <= nums.length <= 3000
-105 <= nums[i] <= 105
四数相加 II
给你四个整数数组 nums1
、nums2
、nums3
和 nums4
,数组长度都是 n
,请你计算有多少个元组 (i, j, k, l)
能满足:
0 <= i, j, k, l < n
nums1[i] + nums2[j] + nums3[k] + nums4[l] == 0
示例 1:
输入:nums1 = [1,2], nums2 = [-2,-1], nums3 = [-1,2], nums4 = [0,2] 输出:2 解释: 两个元组如下: 1. (0, 0, 0, 1) -> nums1[0] + nums2[0] + nums3[0] + nums4[1] = 1 + (-2) + (-1) + 2 = 0 2. (1, 1, 0, 0) -> nums1[1] + nums2[1] + nums3[0] + nums4[0] = 2 + (-1) + (-1) + 0 = 0
示例 2:
输入:nums1 = [0], nums2 = [0], nums3 = [0], nums4 = [0] 输出:1
提示:
n == nums1.length
n == nums2.length
n == nums3.length
n == nums4.length
1 <= n <= 200
-228 <= nums1[i], nums2[i], nums3[i], nums4[i] <= 228