15. 三数之和
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有满足条件且不重复的三元组。
注意:答案中不可以包含重复的三元组。
示例:
给定数组 nums = [-1, 0, 1, 2, -1, -4],
满足要求的三元组集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]
算法思路:排序 + 双指针
- 特判,对于数组长度 len,如果数组为 null 或者数组长度小于 3,返回 []。
- 对数组进行排序。
- 遍历排序后数组:
- 若 nums[i]>0:因为已经排序好,所以后面不可能有三个数加和等于 0,直接返回结果。
- 对于重复元素:跳过,避免出现重复解
- 令左指针 b = a + 1,右指针 c = len - 1,当 b < c 时,执行循环:
- 当 nums[a]+nums[b]+nums[c]==0 执行循环,判断左界和右界是否和下一位置重复,去除重复解。并同时将 b, c 移到下一位置,寻找新的解
- 若和大于 0,说明 nums[c] 太大,c 左移,即 c--;
- 若和小于 0,说明 nums[b] 太小,b 右移,即 b++;
参考代码
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> list = new ArrayList<>();
if (nums == null || nums.length < 3) {
return list;
}
// 排序
Arrays.sort(nums);
int a = 0, b = 0, c = 0, len = nums.length, res = 0;
// a 固定外层循环
for (a = 0; a < len - 2; a++) {
// 第一个元素
if (nums[a] > 0) {
break;
}
// 去重
if (a > 0 && nums[a] == nums[a-1]) {
continue;
}
b = a + 1;
c = len - 1;
// 最小值比较
int min = nums[a] + nums[b] + nums[b+1];
if (min > 0) {
break;
}
// 最大值比较
int max = nums[c] + nums[c-1] + nums[c-2];
if (max < 0) {
break;
}
// b、c 双指针夹逼
while (b < c) {
int target = nums[a] + nums[b] + nums[c];
if (target == 0) {
list.add(Arrays.asList(nums[a], nums[b], nums[c]));
b++;
c--;
// 去重
while (b < c && nums[b] == nums[b-1]) {
b++;
}
while (b < c && nums[c] == nums[c + 1]) {
c--;
}
} else if (target > 0){
c--;
} else {
b++;
}
}
}
return list;
}
}
复杂度分析
- 时间复杂度:。数组排序 ,遍历数组 ,双指针遍历 ,总体 ,即 。
- 空间复杂: 。
以上谢谢大家,求赞求赞求赞!
网友评论