Skip to content

Commit ff7e4e9

Browse files
authored
Merge pull request doocs#25 from Mrzhudky/work
Add solution 018 [Java]
2 parents 5d10ac9 + 408e8e9 commit ff7e4e9

File tree

2 files changed

+166
-0
lines changed

2 files changed

+166
-0
lines changed

solution/018.4Sum/README.md

+99
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
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+
1. 将数组排序
27+
2. 先假设确定一个数 nums[i] 将 4Sum 问题转换为 3Sum 问题;
28+
3. 再假设确定一个数将 3Sum 问题转换为 2Sum 问题;
29+
4. 对排序数组,用首尾指针向中间靠拢的思路寻找满足 target 的 nums[l] 和 nums[k]
30+
31+
```java
32+
class Solution {
33+
public List<List<Integer>> fourSum(int[] nums, int target) {
34+
35+
List<List<Integer>> re = new ArrayList<>();
36+
if(nums == null || nums.length < 4) {
37+
return re;
38+
}
39+
Arrays.sort(nums);
40+
for (int i = 0; i < nums.length - 3; i++) {
41+
42+
// 当 nums[i] 对应的最小组合都大于 target 时,后面大于 nums[i] 的组合必然也大于 target,
43+
if(nums[i] + nums[i+1] + nums[i+2] + nums[i+3] > target) {
44+
break;
45+
}
46+
// 当 nums[i] 对应的最大组合都小于 target 时, nums[i] 的其他组合必然也小于 target
47+
if(nums[i] + nums[nums.length-3] + nums[nums.length-2] + nums[nums.length-1] < target) {
48+
continue;
49+
}
50+
51+
int firstNum = nums[i];
52+
for (int j = i + 1; j < nums.length - 2; j++) {
53+
54+
// nums[j] 过大时,与 nums[i] 过大同理
55+
if(nums[i] + nums[j] + nums[j+1] + nums[j+2] > target) {
56+
break;
57+
}
58+
// nums[j] 过小时,与 nums[i] 过小同理
59+
if(nums[i] + nums[j] + nums[nums.length-2] + nums[nums.length-1] < target) {
60+
continue;
61+
}
62+
63+
int twoSum = target - nums[i] - nums[j];
64+
int l = j + 1;
65+
int k = nums.length - 1;
66+
while (l < k) {
67+
int tempSum = nums[l] + nums[k];
68+
if(tempSum == twoSum) {
69+
ArrayList<Integer> oneGroup = new ArrayList<>(4);
70+
oneGroup.add(nums[i]);
71+
oneGroup.add(nums[j]);
72+
oneGroup.add(nums[l++]);
73+
oneGroup.add(nums[k--]);
74+
re.add(oneGroup);
75+
while (l < nums.length && l < k && nums[l] == oneGroup.get(2) && nums[k] == oneGroup.get(3)) {
76+
l++;k--;
77+
}
78+
}
79+
else if(tempSum < twoSum) {
80+
l++;
81+
}
82+
else {
83+
k--;
84+
}
85+
}
86+
// 跳过重复项
87+
while ((j < nums.length - 2) && (twoSum + nums[i] + nums[j+1] == target)) {
88+
j++;
89+
}
90+
}
91+
// 跳过重复项
92+
while (i < nums.length - 3 && nums[i+1] == firstNum){
93+
i++;
94+
}
95+
}
96+
return re;
97+
}
98+
}
99+
```

solution/018.4Sum/Solution.java

+67
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)