15、三数之和
题目:
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。
注意:答案中不可以包含重复的三元组。
示例 1:
输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
示例 2:
输入:nums = []
输出:[]
示例 3:
输入:nums = [0]
输出:[]
提示:
0 <= nums.length <= 3000
-10^5 <= nums[i] <= 10 ^5
解题思路:
排序 + 双指针
本题的难点在于如何去除重复解。
扫描二维码关注公众号,回复:
14340904 查看本文章
![](/qrcode.jpg)
算法流程:
- 特判,对于数组长度 n,如果数组为 null 或者数组长度小于 3,返回 [ ]。
- 对数组进行排序。
- 遍历排序后数组:
- 若 nums[i]>0nums[i]>0:因为已经排序好,所以后面不可能有三个数加和等于 00,直接返回结果。
- 对于重复元素:跳过,避免出现重复解
- 令左指针 L=i+1,右指针 R=n-1,当 L<R 时,执行循环:
- 当nums[i]+nums[L]+nums[R]==0,执行循环,判断左界和右界是否和下一位置重复,去除重复解。并同时将 L,R 移到下一位置,寻找新的解
- 若和大于 0,说明 nums[R] 太大,R 左移
- 若和小于 0,说明 nums[L]太小,L 右移
参考代码:
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> resList = new ArrayList<>();
// 特殊条件判断
if (nums.length < 3) return resList;
else if (nums.length == 3){
if (nums[0] + nums[1] + nums[2] == 0) {
List<Integer> resSingle = new ArrayList<>();
resSingle.add(nums[0]);
resSingle.add(nums[1]);
resSingle.add(nums[2]);
resList.add(resSingle);
}
return resList;
} else {
// 1.排序
Arrays.sort(nums);
// 2.双指针
for (int j = 0; j < nums.length - 2; j++) {
if (j > 0) {
if (nums[j - 1] == nums[j]) continue;
}
int target = - nums[j];
int l = j + 1;
int r = nums.length - 1;
while (l < r) {
int sum = nums[l] + nums[r];
if (sum < target) l++;
else if (sum > target) r--;
else {
List<Integer> resSingle = new ArrayList<>();
resSingle.add(nums[j]);
resSingle.add(nums[l]);
resSingle.add(nums[r]);
resList.add(resSingle);
l++;
r--;
while (nums[l] == nums[l-1] && nums[r] == nums[r+1] && l < r) {
l++;
r--;
}
}
}
}
return resList;
}
}
}