Skip to content

Commit 98a3c45

Browse files
authored
docs: add a description of the solution to lc problem: No.0015 (#756)
No.0015.3Sum
1 parent 7e5d309 commit 98a3c45

File tree

1 file changed

+33
-6
lines changed

1 file changed

+33
-6
lines changed

solution/0000-0099/0015.3Sum/README.md

+33-6
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,34 @@
4646

4747
<!-- 这里可写通用的实现逻辑 -->
4848

49-
“排序 + 双指针”实现。
49+
若是使用三层嵌套循环,必然会导致程序超时,需要寻找其它方法。
50+
51+
因为不是返回对应的索引,所以可以对数组进行排序。
52+
53+
1.`nums` 进行排序。
54+
2. 遍历数组,并以当前遍历位置作为分割线,在右侧数组当中(不包括分割元素在内),寻找两个可以组成 `0 - nums[i]` 的值,将该题转换为**两数之和**
55+
56+
> 更贴切的说,与 [剑指 Offer 57. 和为s的两个数字](https://leetcode-cn.com/problems/he-wei-sde-liang-ge-shu-zi-lcof/) 目标一致
57+
58+
**优化:**
59+
60+
-`nums[i] > 0` 时,其后续的数值都比 `nums[i]` 大,那么就不可能存在两个数值一起组合为 0,可以提前结束遍历。
61+
- 若当前遍历数值与上一个数值一致(`nums[i] == nums[i - 1]`),可直接跳过(去重复)。
62+
- 相比两数之和,与其不同的是:**目标数组是有序的**。可使用**二分查找****头尾指针**快速搜索目标。
63+
64+
**重复问题:**
65+
66+
最简易的方式便是使用哈希表。还有一种技巧:**双指针**
67+
68+
能够使用双指针(头尾指针)搜索目标是因为**数组是有序的**,当移动指针时,数值的变化可预测的。
69+
70+
> 此处头尾指针使用 `l``r` 表示。
71+
72+
当找到目标值之后,`l``r` 都需要进行移动,并且是**移动到不等于组合时的值**。如 `nums[l] == 0`,那么 `l` 需要移动至 `nums[l] != 0` 的位置,`r` 同理。
73+
74+
为什么要同时移动两个指针,不会导致错过答案吗?并不会,如一个符合题意的组合是 `[-1, 0, 1]`,当 `l` 移动到了非 0 的位置时,那么 `nums[r] = 1` 不可能再组合出一个不重复的答案。
75+
76+
> 需注意,该技巧需要与第二条优化一起使用。
5077
5178
<!-- tabs:start -->
5279

@@ -237,7 +264,7 @@ public class ThreeSumComparer: IEqualityComparer<IList<int>>
237264
{
238265
return left[0] == right[0] && left[1] == right[1] && left[2] == right[2];
239266
}
240-
267+
241268
public int GetHashCode(IList<int> obj)
242269
{
243270
return (obj[0] ^ obj[1] ^ obj[2]).GetHashCode();
@@ -248,7 +275,7 @@ public class Solution {
248275
public IList<IList<int>> ThreeSum(int[] nums) {
249276
Array.Sort(nums);
250277
var results = new HashSet<IList<int>>(new ThreeSumComparer());
251-
278+
252279
var cIndex = Array.BinarySearch(nums, 0);
253280
if (cIndex < 0) cIndex = ~cIndex;
254281
while (cIndex < nums.Length)
@@ -276,7 +303,7 @@ public class Solution {
276303
step /= 2;
277304
}
278305
}
279-
306+
280307
if (nums[aIndex] + nums[bIndex] + c > 0)
281308
{
282309
var step = 1;
@@ -295,7 +322,7 @@ public class Solution {
295322
step /= 2;
296323
}
297324
}
298-
325+
299326
if (nums[aIndex] + nums[bIndex] + c == 0)
300327
{
301328
var list = new List<int> { nums[aIndex], nums[bIndex], c };
@@ -314,7 +341,7 @@ public class Solution {
314341
}
315342
++cIndex;
316343
}
317-
344+
318345
return results.ToList();
319346
}
320347
}

0 commit comments

Comments
 (0)