LeetCode-Q18-四数之和

Q18.四数之和

给你一个由 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:

1
2
输入:nums = [1,0,-1,0,-2,2], target = 0
输出:[[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]]

示例 2:

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$

思路

  1. 可以发现n数之和,可以递归转化为求数组中的n-1数之和
  2. 递归最终就是求解两数之和,可以通过排序数组左右指针的方式求出所有解法
  3. 注意,需要排除重复的解法,对于从左向右的求解过程中,只要元素值相同就不需要重复计算可以跳过。
  4. 由于target在计算过程中不断变化,为了防止溢出可以将target设置为long
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
public List<List<Integer>> fourSum(int[] nums, int target) {
Arrays.sort(nums);
return nSum(nums,0,target,4);
}
public List<List<Integer>> nSum(int[] nums, int start, long target,int n) {
if(n<2 || start>=nums.length){
return new ArrayList<List<Integer>>();
}
if(n==2){
return twoSum(nums,start,target);
}
List<List<Integer>> solutions = new ArrayList<>();
for (int i = start; i < nums.length-n+1; i++) {
if(i>start && nums[i] == nums[i-1]){
continue;
}
int item = nums[i];
List<List<Integer>> match = nSum(nums,i+1,target-item,n-1);
match.forEach(x->{
List<Integer> solution= new ArrayList<>();
solution.add(item);
solution.addAll(x);
solutions.add(solution);
});
}
return solutions;
}
// 注意target 设置为long 防止溢出
public List<List<Integer>> twoSum(int[] nums, int start, long target) {
List<List<Integer>> solutions = new ArrayList<>();
int left= start;
int right = nums.length-1;
while(left<right){ // 终止条件
if(nums[left] + nums[right]> target){
right--;
}else if(nums[left] + nums[right]< target) {
left++;
}else{
if (nums[left] + nums[right] == target) {
List<Integer> solution = new ArrayList<>();
solution.add(nums[left]);
solution.add(nums[right]);
solutions.add(solution);
while (left<right && nums[left] == nums[left+1] ){
left++;
}
while (left<right && nums[right] == nums[right-1]){
right--;
}
left ++;
}
}
}
return solutions;
}