Skip to content

Commit 78a6fa6

Browse files
committed
018.四数之和[Java]
1 parent cf59a22 commit 78a6fa6

File tree

2 files changed

+163
-0
lines changed

2 files changed

+163
-0
lines changed

solution/018.4Sum/README.md

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
## 四数之和
2+
### 题目描述
3+
4+
给定一个包含 n 个整数的数组 nums 和一个目标值 target,
5+
判断 nums 中是否存在四个元素 a,b,c 和 d ,
6+
使得 a + b + c + d 的值与 target 相等?
7+
找出所有满足条件且不重复的四元组。
8+
9+
注意:
10+
11+
答案中不可以包含重复的四元组。
12+
13+
示例:
14+
15+
给定数组 nums = [1, 0, -1, 0, -2, 2],和 target = 0。
16+
17+
满足要求的四元组集合为:
18+
[
19+
[-1, 0, 0, 1],
20+
[-2, -1, 1, 2],
21+
[-2, 0, 0, 2]
22+
]
23+
24+
25+
### 解法
26+
先将4Sum问题,转换为3Sum问题,再转换为2Sum问题.
27+
28+
```java
29+
class Solution {
30+
public List<List<Integer>> fourSum(int[] nums, int target) {
31+
32+
List<List<Integer>> re = new ArrayList<>();
33+
if(nums == null || nums.length<4){
34+
return re;
35+
}
36+
Arrays.sort(nums);
37+
for (int i = 0; i < nums.length-3; i++) {
38+
39+
//当 nums[i] 对应的最小组合都大于 target 时,后面大于 nums[i] 的组合必然也大于 target,
40+
if(nums[i]+nums[i+1]+nums[i+2]+nums[i+3] > target){
41+
break;
42+
}
43+
// 当 nums[i] 对应的最大组合都小于 target 时, nums[i] 的其他组合必然也小于 target
44+
if(nums[i]+nums[nums.length-3]+nums[nums.length-2] + nums[nums.length-1] < target){
45+
continue;
46+
}
47+
48+
int firstNum = nums[i];
49+
for (int j = i+1; j < nums.length-2; j++) {
50+
51+
// nums[j] 过大时,与nums[i]过大同理
52+
if(nums[i]+nums[j]+nums[j+1]+nums[j+2] > target){
53+
break;
54+
}
55+
// nums[j] 过小时,与nums[i]过小同理
56+
if(nums[i]+nums[j]+nums[nums.length-2] + nums[nums.length-1] < target){
57+
continue;
58+
}
59+
60+
int twoSum = target - nums[i]-nums[j];
61+
int l = j+1;
62+
int k = nums.length-1;
63+
while (l<k){
64+
int tempSum = nums[l] + nums[k];
65+
if(tempSum == twoSum){
66+
ArrayList<Integer> oneGroup = new ArrayList<>(4);
67+
oneGroup.add(nums[i]);
68+
oneGroup.add(nums[j]);
69+
oneGroup.add(nums[l++]);
70+
oneGroup.add(nums[k--]);
71+
re.add(oneGroup);
72+
while (l<nums.length && l<k && nums[l] == oneGroup.get(2) && nums[k] == oneGroup.get(3)){
73+
l++;k--;
74+
}
75+
}
76+
else if(tempSum<twoSum){
77+
l++;
78+
}
79+
else{
80+
k--;
81+
}
82+
}
83+
// 跳过重复项
84+
while ((j<nums.length-2)&&(twoSum + nums[i] + nums[j+1] == target)){
85+
j++;
86+
}
87+
}
88+
// 跳过重复项
89+
while (i<nums.length-3 &&(nums[i+1] == firstNum) ){
90+
i++;
91+
}
92+
}
93+
return re;
94+
}
95+
}
96+
```

solution/018.4Sum/Solution.java

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
class Solution {
2+
public List<List<Integer>> fourSum(int[] nums, int target) {
3+
4+
List<List<Integer>> re = new ArrayList<>();
5+
if(nums == null || nums.length<4){
6+
return re;
7+
}
8+
Arrays.sort(nums);
9+
for (int i = 0; i < nums.length-3; i++) {
10+
11+
//当 nums[i] 对应的最小组合都大于 target 时,后面大于 nums[i] 的组合必然也大于 target,
12+
if(nums[i]+nums[i+1]+nums[i+2]+nums[i+3] > target){
13+
break;
14+
}
15+
// 当 nums[i] 对应的最大组合都小于 target 时, nums[i] 的其他组合必然也小于 target
16+
if(nums[i]+nums[nums.length-3]+nums[nums.length-2] + nums[nums.length-1] < target){
17+
continue;
18+
}
19+
20+
int firstNum = nums[i];
21+
for (int j = i+1; j < nums.length-2; j++) {
22+
23+
// nums[j] 过大时,与nums[i]过大同理
24+
if(nums[i]+nums[j]+nums[j+1]+nums[j+2] > target){
25+
break;
26+
}
27+
// nums[j] 过小时,与nums[i]过小同理
28+
if(nums[i]+nums[j]+nums[nums.length-2] + nums[nums.length-1] < target){
29+
continue;
30+
}
31+
32+
int twoSum = target - nums[i]-nums[j];
33+
int l = j+1;
34+
int k = nums.length-1;
35+
while (l<k){
36+
int tempSum = nums[l] + nums[k];
37+
if(tempSum == twoSum){
38+
ArrayList<Integer> oneGroup = new ArrayList<>(4);
39+
oneGroup.add(nums[i]);
40+
oneGroup.add(nums[j]);
41+
oneGroup.add(nums[l++]);
42+
oneGroup.add(nums[k--]);
43+
re.add(oneGroup);
44+
while (l<nums.length && l<k && nums[l] == oneGroup.get(2) && nums[k] == oneGroup.get(3)){
45+
l++;k--;
46+
}
47+
}
48+
else if(tempSum<twoSum){
49+
l++;
50+
}
51+
else{
52+
k--;
53+
}
54+
}
55+
// 跳过重复项
56+
while ((j<nums.length-2)&&(twoSum + nums[i] + nums[j+1] == target)){
57+
j++;
58+
}
59+
}
60+
// 跳过重复项
61+
while (i<nums.length-3 &&(nums[i+1] == firstNum) ){
62+
i++;
63+
}
64+
}
65+
return re;
66+
}
67+
}

0 commit comments

Comments
 (0)