Skip to content

Commit fc74cc7

Browse files
committedMar 6, 2025·
三刷15
1 parent 4828b21 commit fc74cc7

File tree

4 files changed

+128
-16
lines changed

4 files changed

+128
-16
lines changed
 

‎docs/0000-00-recursion.adoc

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
[#0000-00-recursion]
2-
= 递归
2+
= Recursion 递归
3+
4+
一个粗浅的认识:递归在部分场景中,可以当做一个循环来推进数组的下标。例如:
5+
6+
. xref:0015-3sum.adoc[15. 3Sum]
7+
8+
39

410
== 经典题目
511

‎docs/0015-3sum.adoc

+43-15
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,45 @@
11
[#0015-3sum]
2-
= 15. 3Sum
2+
= 15. 三数之和
33

4-
{leetcode}/problems/3sum/[LeetCode - 3Sum^]
4+
https://leetcode.cn/problems/3sum/[LeetCode - 15. 三数之和 ^]
55

6-
Given an array `nums` of _n_ integers, are there elements _a_, _b_, _c_ in `nums` such that _a_ + _b_ + _c_ = 0? Find all unique triplets in the array which gives the sum of zero.
6+
给你一个整数数组 `nums` ,判断是否存在三元组 `+[nums[i], nums[j], nums[k]]+` 满足 `+i != j+``+i != k+``+j != k+` ,同时还满足 `+nums[i] + nums[j] + nums[k] == 0+`。请你返回所有和为 `0` 且不重复的三元组。
77

8-
*Note:*
8+
**注意:**答案中不可以包含重复的三元组。
99

10-
The solution set must not contain duplicate triplets.
10+
*示例 1:*
1111

12-
*Example:*
12+
....
13+
输入:nums = [-1,0,1,2,-1,-4]
14+
输出:[[-1,-1,2],[-1,0,1]]
15+
解释:
16+
nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0 。
17+
nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 。
18+
nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。
19+
不同的三元组是 [-1,0,1] 和 [-1,-1,2] 。
20+
注意,输出的顺序和三元组的顺序并不重要。
21+
....
1322

14-
[subs="verbatim,quotes,macros"]
15-
----
16-
Given array nums = [-1, 0, 1, 2, -1, -4],
23+
*示例 2:*
1724

18-
A solution set is:
19-
[
20-
[-1, 0, 1],
21-
[-1, -1, 2]
22-
]
23-
----
25+
....
26+
输入:nums = [0,1,1]
27+
输出:[]
28+
解释:唯一可能的三元组和不为 0 。
29+
....
30+
31+
*示例 3:*
32+
33+
....
34+
输入:nums = [0,0,0]
35+
输出:[[0,0,0]]
36+
解释:唯一可能的三元组和为 0 。
37+
....
38+
39+
*提示:*
40+
41+
* `+3 <= nums.length <= 3000+`
42+
* `+-10+`^`+5+`^`+<= nums[i] <= 10+`^`+5+`^
2443
2544
== 解题分析
2645

@@ -55,6 +74,15 @@ include::{sourcedir}/_0015_3Sum_20.java[tag=answer]
5574
include::{sourcedir}/_0015_3Sum_21.java[tag=answer]
5675
----
5776
--
77+
78+
三刷::
79+
+
80+
--
81+
[{java_src_attr}]
82+
----
83+
include::{sourcedir}/_0015_3Sum_3.java[tag=answer]
84+
----
85+
--
5886
====
5987

6088
== 参考资料

‎logbook/202503.adoc

+5
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@ endif::[]
4040
|{doc_base_url}/0001-two-sum.adoc[题解]
4141
|✅ 注意审题!返回的是数组下标。
4242

43+
|{counter:codes2503}
44+
|{leetcode_base_url}/3sum/[15. 三数之和^]
45+
|{doc_base_url}/0015-3sum.adoc[题解]
46+
|✅ 双指针
47+
4348
|===
4449

4550
截止目前,本轮练习一共完成 {codes2503} 道题。
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
package com.diguage.algo.leetcode;
2+
3+
import java.util.ArrayList;
4+
import java.util.Arrays;
5+
import java.util.List;
6+
7+
public class _0015_3Sum_3 {
8+
// tag::answer[]
9+
10+
/**
11+
* @author D瓜哥 · https://www.diguage.com
12+
* @since 2025-03-06 16:53:23
13+
*/
14+
public List<List<Integer>> threeSum(int[] nums) {
15+
Arrays.sort(nums);
16+
return numsSum(nums, 0, 3, 0);
17+
}
18+
19+
/**
20+
* 通用方法,可以处理 count 数之和
21+
*/
22+
private List<List<Integer>> numsSum(int[] nums, int idx, int count, int sum) {
23+
// 剩余数组长度不够,直接返回
24+
if (nums.length - idx < count || count < 2) {
25+
return new ArrayList<>();
26+
}
27+
List<List<Integer>> result = new ArrayList<>();
28+
if (count == 2) {
29+
int left = idx, right = nums.length - 1;
30+
while (left < right) {
31+
int leftNum = nums[left];
32+
int rightNum = nums[right];
33+
int iSum = leftNum + rightNum;
34+
if (iSum == sum) {
35+
result.add(new ArrayList<>(Arrays.asList(leftNum, rightNum)));
36+
// 不允许有重复数组,则将重复元素都排除掉
37+
while (left < right && leftNum == nums[left]) {
38+
left++;
39+
}
40+
while (left < right && rightNum == nums[right]) {
41+
right--;
42+
}
43+
} else if (iSum < sum) {
44+
while (left < right && leftNum == nums[left]) {
45+
left++;
46+
}
47+
} else {
48+
while (left < right && rightNum == nums[right]) {
49+
right--;
50+
}
51+
}
52+
}
53+
return result;
54+
} else {
55+
for (int i = idx; i < nums.length; i++) {
56+
int num = nums[i];
57+
// 在这里,递归相当一层循环,无论 count 值多大,就可以通过增加递归次数,来降低 count 的值
58+
List<List<Integer>> lists = numsSum(nums, i + 1, count - 1, sum - num);
59+
for (List<Integer> list : lists) {
60+
list.add(num);
61+
result.add(list);
62+
}
63+
// 不允许有重复数组,则将重复元素都排除掉
64+
// 使用 nums[i] == nums[i + 1] 来判断,因为执行完该语句之后,还有一个 i++ 要执行
65+
while (i < nums.length - 1 && nums[i] == nums[i + 1]) {
66+
i++;
67+
}
68+
}
69+
}
70+
return result;
71+
}
72+
// end::answer[]
73+
}

0 commit comments

Comments
 (0)
Please sign in to comment.