LeetCode LCR 007. 三数之和
题目描述
思路分析
解法一:排序 + 双指针(推荐)
核心思路:
- 先排序,方便双指针与去重。
- 枚举第一个数
nums[i],在区间[i+1, n-1]使用双指针寻找和为-nums[i]的两数。- 找到解后跳过重复元素,保证不重不漏。
复杂度分析:
- 时间复杂度:O(n^2),其中 n 表示数组长度。
- 空间复杂度:O(1),不计结果集。
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> res = new ArrayList<>();
if (nums == null || nums.length < 3) {
return res;
}
Arrays.sort(nums);
int n = nums.length;
for (int i = 0; i < n - 2; i++) {
if (nums[i] > 0) {
// 最小值已大于 0,不可能再凑出 0
break;
}
if (i > 0 && nums[i] == nums[i - 1]) {
// 跳过重复的第一个数
continue;
}
int left = i + 1;
int right = n - 1;
while (left < right) {
int sum = nums[i] + nums[left] + nums[right];
if (sum == 0) {
res.add(Arrays.asList(nums[i], nums[left], nums[right]));
// 跳过重复的 left
while (left < right && nums[left] == nums[left + 1]) {
left++;
}
// 跳过重复的 right
while (left < right && nums[right] == nums[right - 1]) {
right--;
}
left++;
right--;
} else if (sum < 0) {
left++;
} else {
right--;
}
}
}
return res;
}
}
func threeSum(nums []int) [][]int {
var res [][]int
if len(nums) < 3 {
return res
}
sort.Ints(nums)
n := len(nums)
for i := 0; i < n-2; i++ {
if nums[i] > 0 {
// 最小值已大于 0,不可能再凑出 0
break
}
if i > 0 && nums[i] == nums[i-1] {
// 跳过重复的第一个数
continue
}
left, right := i+1, n-1
for left < right {
sum := nums[i] + nums[left] + nums[right]
if sum == 0 {
res = append(res, []int{nums[i], nums[left], nums[right]})
// 跳过重复的 left
for left < right && nums[left] == nums[left+1] {
left++
}
// 跳过重复的 right
for left < right && nums[right] == nums[right-1] {
right--
}
left++
right--
} else if sum < 0 {
left++
} else {
right--
}
}
}
return res
}
相似题目
| 题目 | 难度 | 考察点 |
|---|---|---|
| 1. 两数之和 | 简单 | 哈希表 |
| 167. 两数之和 II - 输入有序数组 | 中等 | 排序 + 双指针 |
| 16. 最接近的三数之和 | 中等 | 排序 + 双指针 |
| 18. 四数之和 | 中等 | 排序 + 双指针 + 去重 |
| 259. 较小的三数之和 | 中等 | 排序 + 双指针 |
| 923. 三数之和的多种可能 | 中等 | 排序 + 双指针 + 计数 |
| 11. 盛最多水的容器 | 中等 | 双指针贪心 |
本博客所有文章除特别声明外,均采用
CC BY-NC-SA 4.0
许可协议,转载请注明出处!