|
1 | 1 | # 15. 三数之和 |
2 | 2 |
|
3 | | -> **作者:** 弘树 |
4 | | -> **日期:** 2024-08-28 |
| 3 | +> **日期**:2024-08-28 |
| 4 | +> **所用时间**:15min |
| 5 | +> **知识点**:排序、双指针 |
5 | 6 |
|
6 | | -## 解题思路 |
7 | | -### 1.双指针 |
| 7 | +## 1. 题目描述 |
8 | 8 |
|
9 | | -首先进行排序,然后从小到大固定住每一个元素$k$,之后问题转换为在子序列$[k, len(nums)]$中寻找和为$-nums[k]$的两个元素,之后就可以使用双指针算法。 |
| 9 | +给定一个整数数组 `nums`,找出所有**和为 0** 的三元组 `[nums[i], nums[j], nums[k]]`,其中三个下标 `i`、`j`、`k` 互不相同。 |
10 | 10 |
|
11 | | -- 时间复杂度:$O(n^2)$ |
12 | | -- 空间复杂度:$O(1)$ |
| 11 | +**要求**:返回所有满足条件且**不重复**的三元组。重复的三元组只保留一份。 |
| 12 | + |
| 13 | +**示例 1:** |
| 14 | + |
| 15 | +- **输入**:nums = [-1,0,1,2,-1,-4] |
| 16 | +- **输出**:[[-1,-1,2],[-1,0,1]] |
| 17 | +- **解释**:(-1) + 0 + 1 = 0;(-1) + 2 + (-1) = 0。 |
| 18 | + |
| 19 | +**示例 2:** |
| 20 | + |
| 21 | +- **输入**:nums = [0,1,1] |
| 22 | +- **输出**:[] |
| 23 | +- **解释**:唯一可能的三元组之和不为 0。 |
| 24 | + |
| 25 | +**示例 3:** |
| 26 | + |
| 27 | +- **输入**:nums = [0,0,0] |
| 28 | +- **输出**:[[0,0,0]] |
| 29 | + |
| 30 | +**约束:** |
| 31 | + |
| 32 | +- $3 \le \text{nums.length} \le 3000$ |
| 33 | +- $-10^5 \le \text{nums}[i] \le 10^5$ |
| 34 | + |
| 35 | +--- |
| 36 | + |
| 37 | +## 2. 排序 + 双指针 |
| 38 | + |
| 39 | +先对数组**排序**,再从小到大**固定**第一个数 $nums[k]$,问题转化为在 $[k+1, n-1]$ 区间内找两个数之和为 $-nums[k]$,可用**双指针**在有序区间内相向扫描:左指针 $i$、右指针 $j$,若 $nums[i]+nums[j] < -nums[k]$ 则 $i$ 右移,若大于则 $j$ 左移,等于则记录一组解并同时收缩 $i$、$j$。为**去重**:固定 $k$ 时若 $nums[k]=nums[k-1]$ 则跳过;找到一组解后把 $i$、$j$ 移到与当前值不同的位置再继续。 |
| 40 | + |
| 41 | +**复杂度分析:** |
| 42 | + |
| 43 | +- 时间复杂度:$O(n^2)$(排序 $O(n\log n)$,外层枚举 $k$ $O(n)$,内层双指针 $O(n)$) |
| 44 | +- 空间复杂度:$O(1)$(不计返回结果与排序栈,若 sort 原地则为 $O(1)$) |
| 45 | + |
| 46 | +**Python3** |
| 47 | + |
| 48 | +```python |
| 49 | +class Solution: |
| 50 | + def threeSum(self, nums: list[int]) -> list[list[int]]: |
| 51 | + ans = [] |
| 52 | + nums.sort() |
| 53 | + n = len(nums) |
| 54 | + |
| 55 | + for k, x in enumerate(nums): |
| 56 | + if k and nums[k] == nums[k - 1]: |
| 57 | + continue |
| 58 | + target = -x |
| 59 | + i, j = k + 1, n - 1 |
| 60 | + while i < j: |
| 61 | + if nums[i] + nums[j] > target: |
| 62 | + j -= 1 |
| 63 | + elif nums[i] + nums[j] < target: |
| 64 | + i += 1 |
| 65 | + else: |
| 66 | + ans.append([x, nums[i], nums[j]]) |
| 67 | + while i < j and nums[i] == nums[i + 1]: |
| 68 | + i += 1 |
| 69 | + while i < j and nums[j] == nums[j - 1]: |
| 70 | + j -= 1 |
| 71 | + i += 1 |
| 72 | + j -= 1 |
| 73 | + return ans |
| 74 | +``` |
| 75 | + |
| 76 | +**C++** |
13 | 77 |
|
14 | 78 | ```C++ |
15 | 79 | class Solution { |
@@ -38,4 +102,4 @@ public: |
38 | 102 | return ans; |
39 | 103 | } |
40 | 104 | }; |
41 | | -``` |
| 105 | +``` |
0 commit comments