Skip to content

Commit 352b9ea

Browse files
committed
Update solution 018 [Java]
1 parent ff7e4e9 commit 352b9ea

File tree

3 files changed

+149
-43
lines changed

3 files changed

+149
-43
lines changed

README.md

+2
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ Complete [solutions](https://github.com/doocs/leetcode/tree/master/solution) to
5555
| 003 | [Longest Substring Without Repeating Characters](https://github.com/doocs/leetcode/tree/master/solution/003.Longest%20Substring%20Without%20Repeating%20Characters) | `Hash Table`, `Two Pointers`, `String` |
5656
| 005 | [Longest Palindromic Substring](https://github.com/doocs/leetcode/tree/master/solution/005.Longest%20Palindromic%20Substring) | `String`, `Dynamic Programming` |
5757
| 015 | [3Sum](https://github.com/doocs/leetcode/tree/master/solution/015.3Sum) | `Array`, `Two Pointers` |
58+
| 018 | [4Sum](https://github.com/doocs/leetcode/tree/master/solution/018.4Sum) | `Array`, `Hash Table`, `Two Pointers` |
5859
| 019 | [Remove Nth Node From End of List](https://github.com/doocs/leetcode/tree/master/solution/019.Remove%20Nth%20Node%20From%20End%20of%20List) | `Linked List`, `Two Pointers` |
5960
| 024 | [Swap Nodes in Pairs](https://github.com/doocs/leetcode/tree/master/solution/024.Swap%20Nodes%20in%20Pairs) | `Linked List` |
6061
| 031 | [Next Permutation](https://github.com/doocs/leetcode/tree/master/solution/031.Next%20Permutation) | `Array` |
@@ -105,5 +106,6 @@ I'm looking for long-term contributors/partners to this repo! Send me [PRs](http
105106
<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
106107
| <center> [<img src="https://avatars3.githubusercontent.com/u/21008209?v=4" width="80px;"/>](https://github.com/yanglbme)<br />[💻](https://github.com/doocs/leetcode/commits?author=yanglbme "Code") </center> | <center> [<img src="https://avatars3.githubusercontent.com/u/23625436?v=4" width="80px;"/>](https://github.com/chakyam)<br />[💻](https://github.com/doocs/leetcode/commits?author=chakyam "Code") </center> | <center> [<img src="https://avatars3.githubusercontent.com/u/10081554?v=4" width="80px;"/>](https://github.com/zhkmxx9302013)<br />[💻](https://github.com/doocs/leetcode/commits?author=zhkmxx9302013 "Code") </center> | <center> [<img src="https://avatars3.githubusercontent.com/u/40383345?v=4" width="80px;"/>](https://github.com/MarkKuang1991)<br />[💻](https://github.com/doocs/leetcode/commits?author=MarkKuang1991 "Code") </center> | <center> [<img src="https://avatars3.githubusercontent.com/u/12371194?v=4" width="80px;"/>](https://github.com/fonxian)<br />[💻](https://github.com/doocs/leetcode/commits?author=fonxian "Code") </center> | <center> [<img src="https://avatars3.githubusercontent.com/u/25222367?v=4" width="80px;"/>](https://github.com/zhanary)<br />[💻](https://github.com/doocs/leetcode/commits?author=zhanary "Code") </center> | <center> [<img src="https://avatars3.githubusercontent.com/u/42396616?v=4" width="80px;"/>](https://github.com/ZhouTingZhaobiu)<br />[💻](https://github.com/doocs/leetcode/commits?author=ZhouTingZhaobiu "Code") </center> | <center> [<img src="https://avatars3.githubusercontent.com/u/31923541?v=4" width="80px;"/>](https://github.com/zouwx2cs)<br />[💻](https://github.com/doocs/leetcode/commits?author=zouwx2cs "Code") </center> |
107108
|---|---|---|---|---|---|---|---|
109+
| <center> [<img src="https://avatars3.githubusercontent.com/u/20679510?v=4" width="80px;"/>](https://github.com/Mrzhudky)<br />[💻](https://github.com/doocs/leetcode/commits?author=Mrzhudky "Code") </center> |
108110

109111
<!-- ALL-CONTRIBUTORS-LIST:END -->

solution/018.4Sum/README.md

+79-25
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,14 @@
11
## 四数之和
22
### 题目描述
33

4-
给定一个包含 n 个整数的数组 nums 和一个目标值 target,
5-
判断 nums 中是否存在四个元素 a,b,c 和 d ,
6-
使得 a + b + c + d 的值与 target 相等?
7-
找出所有满足条件且不重复的四元组。
4+
给定一个包含 n 个整数的数组 `nums` 和一个目标值 `target`,判断 `nums` 中是否存在四个元素 a,b,c 和 d ,使得 a + b + c + d 的值与 `target` 相等?找出所有满足条件且不重复的四元组。
85

9-
注意:
6+
**注意:**
107

118
答案中不可以包含重复的四元组。
129

13-
示例:
14-
10+
**示例:**
11+
```
1512
给定数组 nums = [1, 0, -1, 0, -2, 2],和 target = 0。
1613
1714
满足要求的四元组集合为:
@@ -20,43 +17,46 @@
2017
[-2, -1, 1, 2],
2118
[-2, 0, 0, 2]
2219
]
20+
```
2321

2422

2523
### 解法
26-
1. 将数组排序
24+
25+
#### 解法一
26+
1. 将数组排序;
2727
2. 先假设确定一个数 nums[i] 将 4Sum 问题转换为 3Sum 问题;
2828
3. 再假设确定一个数将 3Sum 问题转换为 2Sum 问题;
2929
4. 对排序数组,用首尾指针向中间靠拢的思路寻找满足 target 的 nums[l] 和 nums[k]
3030

3131
```java
3232
class Solution {
3333
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;
34+
35+
List<List<Integer>> re = new ArrayList<>();
36+
if (nums == null || nums.length < 4) {
37+
return re;
3838
}
3939
Arrays.sort(nums);
4040
for (int i = 0; i < nums.length - 3; i++) {
41-
41+
4242
// 当 nums[i] 对应的最小组合都大于 target 时,后面大于 nums[i] 的组合必然也大于 target,
43-
if(nums[i] + nums[i+1] + nums[i+2] + nums[i+3] > target) {
43+
if (nums[i] + nums[i + 1] + nums[i + 2] + nums[i + 3] > target) {
4444
break;
4545
}
4646
// 当 nums[i] 对应的最大组合都小于 target 时, nums[i] 的其他组合必然也小于 target
47-
if(nums[i] + nums[nums.length-3] + nums[nums.length-2] + nums[nums.length-1] < target) {
47+
if (nums[i] + nums[nums.length - 3] + nums[nums.length - 2] + nums[nums.length - 1] < target) {
4848
continue;
4949
}
5050

5151
int firstNum = nums[i];
5252
for (int j = i + 1; j < nums.length - 2; j++) {
5353

5454
// nums[j] 过大时,与 nums[i] 过大同理
55-
if(nums[i] + nums[j] + nums[j+1] + nums[j+2] > target) {
55+
if (nums[i] + nums[j] + nums[j + 1] + nums[j + 2] > target) {
5656
break;
5757
}
5858
// nums[j] 过小时,与 nums[i] 过小同理
59-
if(nums[i] + nums[j] + nums[nums.length-2] + nums[nums.length-1] < target) {
59+
if (nums[i] + nums[j] + nums[nums.length - 2] + nums[nums.length - 1] < target) {
6060
continue;
6161
}
6262

@@ -65,35 +65,89 @@ class Solution {
6565
int k = nums.length - 1;
6666
while (l < k) {
6767
int tempSum = nums[l] + nums[k];
68-
if(tempSum == twoSum) {
68+
if (tempSum == twoSum) {
6969
ArrayList<Integer> oneGroup = new ArrayList<>(4);
7070
oneGroup.add(nums[i]);
7171
oneGroup.add(nums[j]);
7272
oneGroup.add(nums[l++]);
7373
oneGroup.add(nums[k--]);
7474
re.add(oneGroup);
7575
while (l < nums.length && l < k && nums[l] == oneGroup.get(2) && nums[k] == oneGroup.get(3)) {
76-
l++;k--;
76+
l++;
77+
k--;
7778
}
78-
}
79-
else if(tempSum < twoSum) {
79+
} else if (tempSum < twoSum) {
8080
l++;
81-
}
82-
else {
81+
} else {
8382
k--;
8483
}
8584
}
8685
// 跳过重复项
87-
while ((j < nums.length - 2) && (twoSum + nums[i] + nums[j+1] == target)) {
86+
while ((j < nums.length - 2) && (twoSum + nums[i] + nums[j + 1] == target)) {
8887
j++;
8988
}
9089
}
9190
// 跳过重复项
92-
while (i < nums.length - 3 && nums[i+1] == firstNum){
91+
while (i < nums.length - 3 && nums[i + 1] == firstNum) {
9392
i++;
9493
}
9594
}
9695
return re;
9796
}
9897
}
98+
```
99+
100+
#### 解法二
101+
对数组进行排序,利用指针 `i`, `j` 固定前两个数,`p`, `q` 指向剩余数组的首尾,判断四数和是否为 `target`
102+
- 若是,添加到 `list` 中。此时 右移 `p` 直到 `nums[p] != nums[p - 1]`(为了去重)。同样,`q` 左移,进行去重。
103+
- 若四数和大于 `target``q` 指针左移;否则 `p` 指针右移。
104+
- 对于外面的两层 `for` 循环,同样需要进行去重操作。
105+
106+
```java
107+
class Solution {
108+
public List<List<Integer>> fourSum(int[] nums, int target) {
109+
Arrays.sort(nums);
110+
int n = nums.length;
111+
List<List<Integer>> list = new ArrayList<>();
112+
int p = 0;
113+
int q = 0;
114+
for (int i = 0; i < n - 3; ++i) {
115+
for (int j = i + 1; j < n - 2; ++j) {
116+
p = j + 1;
117+
q = n - 1;
118+
while (p < q) {
119+
int val = nums[i] + nums[j] + nums[p] + nums[q];
120+
if (val == target) {
121+
list.add(Arrays.asList(nums[i], nums[j], nums[p], nums[q]));
122+
// p 指针右移,直到 nums[p] 与 nums[p - 1] 不等
123+
++p;
124+
while (p < q && nums[p] == nums[p - 1]) {
125+
++p;
126+
}
127+
--q;
128+
while (p < q && nums[q] == nums[q + 1]) {
129+
--q;
130+
}
131+
} else if (val > target) {
132+
--q;
133+
} else {
134+
q = val > target ? q - 1 : q;
135+
p = val < target ? p + 1 : p;
136+
}
137+
}
138+
139+
// j < n - 3:保证 j 不会溢出
140+
while (j < n - 3 && nums[j] == nums[j + 1]) {
141+
++j;
142+
}
143+
}
144+
145+
// i < n - 4:保证 i 不会溢出
146+
while (i < n - 4 && nums[i] == nums[i + 1]) {
147+
++i;
148+
}
149+
}
150+
return list;
151+
}
152+
}
99153
```

solution/018.4Sum/Solution.java

+68-18
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,31 @@
11
class Solution {
22
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;
3+
4+
List<List<Integer>> re = new ArrayList<>();
5+
if (nums == null || nums.length < 4) {
6+
return re;
77
}
88
Arrays.sort(nums);
99
for (int i = 0; i < nums.length - 3; i++) {
10-
10+
1111
// 当 nums[i] 对应的最小组合都大于 target 时,后面大于 nums[i] 的组合必然也大于 target,
12-
if(nums[i] + nums[i+1] + nums[i+2] + nums[i+3] > target) {
12+
if (nums[i] + nums[i + 1] + nums[i + 2] + nums[i + 3] > target) {
1313
break;
1414
}
1515
// 当 nums[i] 对应的最大组合都小于 target 时, nums[i] 的其他组合必然也小于 target
16-
if(nums[i] + nums[nums.length-3] + nums[nums.length-2] + nums[nums.length-1] < target) {
16+
if (nums[i] + nums[nums.length - 3] + nums[nums.length - 2] + nums[nums.length - 1] < target) {
1717
continue;
1818
}
1919

2020
int firstNum = nums[i];
2121
for (int j = i + 1; j < nums.length - 2; j++) {
2222

2323
// nums[j] 过大时,与 nums[i] 过大同理
24-
if(nums[i] + nums[j] + nums[j+1] + nums[j+2] > target) {
24+
if (nums[i] + nums[j] + nums[j + 1] + nums[j + 2] > target) {
2525
break;
2626
}
2727
// nums[j] 过小时,与 nums[i] 过小同理
28-
if(nums[i] + nums[j] + nums[nums.length-2] + nums[nums.length-1] < target) {
28+
if (nums[i] + nums[j] + nums[nums.length - 2] + nums[nums.length - 1] < target) {
2929
continue;
3030
}
3131

@@ -34,34 +34,84 @@ public List<List<Integer>> fourSum(int[] nums, int target) {
3434
int k = nums.length - 1;
3535
while (l < k) {
3636
int tempSum = nums[l] + nums[k];
37-
if(tempSum == twoSum) {
37+
if (tempSum == twoSum) {
3838
ArrayList<Integer> oneGroup = new ArrayList<>(4);
3939
oneGroup.add(nums[i]);
4040
oneGroup.add(nums[j]);
4141
oneGroup.add(nums[l++]);
4242
oneGroup.add(nums[k--]);
4343
re.add(oneGroup);
4444
while (l < nums.length && l < k && nums[l] == oneGroup.get(2) && nums[k] == oneGroup.get(3)) {
45-
l++;k--;
45+
l++;
46+
k--;
4647
}
47-
}
48-
else if(tempSum < twoSum) {
48+
} else if (tempSum < twoSum) {
4949
l++;
50-
}
51-
else {
50+
} else {
5251
k--;
5352
}
5453
}
5554
// 跳过重复项
56-
while ((j < nums.length - 2) && (twoSum + nums[i] + nums[j+1] == target)) {
55+
while ((j < nums.length - 2) && (twoSum + nums[i] + nums[j + 1] == target)) {
5756
j++;
5857
}
5958
}
6059
// 跳过重复项
61-
while (i < nums.length - 3 && nums[i+1] == firstNum){
60+
while (i < nums.length - 3 && nums[i + 1] == firstNum) {
6261
i++;
6362
}
6463
}
6564
return re;
6665
}
67-
}
66+
}
67+
68+
/*
69+
70+
class Solution {
71+
public List<List<Integer>> fourSum(int[] nums, int target) {
72+
Arrays.sort(nums);
73+
int n = nums.length;
74+
List<List<Integer>> list = new ArrayList<>();
75+
int p = 0;
76+
int q = 0;
77+
for (int i = 0; i < n - 3; ++i) {
78+
for (int j = i + 1; j < n - 2; ++j) {
79+
p = j + 1;
80+
q = n - 1;
81+
while (p < q) {
82+
int val = nums[i] + nums[j] + nums[p] + nums[q];
83+
if (val == target) {
84+
list.add(Arrays.asList(nums[i], nums[j], nums[p], nums[q]));
85+
// p 指针右移,直到 nums[p] 与 nums[p - 1] 不等
86+
++p;
87+
while (p < q && nums[p] == nums[p - 1]) {
88+
++p;
89+
}
90+
--q;
91+
while (p < q && nums[q] == nums[q + 1]) {
92+
--q;
93+
}
94+
} else if (val > target) {
95+
--q;
96+
} else {
97+
q = val > target ? q - 1 : q;
98+
p = val < target ? p + 1 : p;
99+
}
100+
}
101+
102+
// j < n - 3:保证 j 不会溢出
103+
while (j < n - 3 && nums[j] == nums[j + 1]) {
104+
++j;
105+
}
106+
}
107+
108+
// i < n - 4:保证 i 不会溢出
109+
while (i < n - 4 && nums[i] == nums[i + 1]) {
110+
++i;
111+
}
112+
}
113+
return list;
114+
}
115+
}
116+
117+
*/

0 commit comments

Comments
 (0)