diff --git a/双指针/3. 三数之和.md b/双指针/3. 三数之和.md new file mode 100644 index 0000000..0d59511 --- /dev/null +++ b/双指针/3. 三数之和.md @@ -0,0 +1,94 @@ +# 三数之和 + +## 题目 +给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请你返回所有和为 0 且不重复的三元组。 + +注意:答案中不可以包含重复的三元组。 + + + + + +示例 1: + +输入:nums = [-1,0,1,2,-1,-4] +输出:[[-1,-1,2],[-1,0,1]] +解释: +nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0 。 +nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 。 +nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。 +不同的三元组是 [-1,0,1] 和 [-1,-1,2] 。 +注意,输出的顺序和三元组的顺序并不重要。 +示例 2: + +输入:nums = [0,1,1] +输出:[] +解释:唯一可能的三元组和不为 0 。 +示例 3: + +输入:nums = [0,0,0] +输出:[[0,0,0]] +解释:唯一可能的三元组和为 0 。 + + +提示: + +3 <= nums.length <= 3000 +-105 <= nums[i] <= 105 + +## 思路 + +- 预处理 + - 排序 +- 三个指针 + - p, l, r + - p: Traverse Full + - l: p+1 -> + - r: <-nums.length-1 +- 降级为两数之和 + + +## 代码 + +```java +class Solution { + public List> threeSum(int[] nums) { + // Pre + Arrays.sort(nums); + // Init + int p, l, r; + List> ans = new ArrayList<>(); + // Traverse 1 + for (p = 0; p < nums.length - 2; p++) { + // DISTINCT + if (p > 0 && nums[p - 1] == nums[p]) { + continue; + } + int target = -nums[p]; + // Pointer + l = p + 1; + r = nums.length - 1; + // Traverse 2: Two Sum + while (l < r) { + int sum = nums[l] + nums[r]; + if (sum < target) l++; + else if (sum > target) r--; + else { + ans.add(Arrays.asList(nums[p],nums[r],nums[l])); + // DISTINCT + while (l < r && nums[l] == nums[l + 1]) { + l++; + } + while (l < r && nums[r] == nums[r - 1]) { + r--; + } + l++; + r--; + } + } + + } + return ans; + } +} +``` \ No newline at end of file