15. 三数之和
难度中等4980
给你一个包含 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
-105 <= nums[i] <= 105
思路
这道题给我的感觉就是,问题不难,细节太多了,预期和实际输出不一样。
这道题的解法就是双指针加二分查找
遍历数组每个节点,然后左指针为当前节点下一个,右指针为最后节点
但是元素不能相同,所以要去重,加上二分查找,先排好序
首先在数组遍历的时候,下一轮遍历的元素的开始,不能和前面一个样(记住我们是排好序的,肯定在左右)
if (i>0&&nums[i]==nums[i-1]){ continue; }
第二点去重就是添加元素之后,在一轮遍历中添加的元素,不能和之前添加的元素一样
while (right>left&&nums[right]==nums[right-1]){ right--; } while (right>left&&nums[left]==nums[left+1]){ left++; }q
去重终结:第一次去重,是为下一轮nums[i] 不能重复,第二次去重是保证,一轮遍历元素中添加元素不能重复,针对的是
nums[right]和nums[left]
题目算法代码如下
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>>arrayList = new ArrayList<>();
Arrays.sort(nums);
for (int i = 0; i < nums.length; i++) {
if (nums[i]>0){
return arrayList;
}
if (i>0&&nums[i]==nums[i-1]){
continue;
}
int left=i+1;
int right =nums.length-1;
while (right>left){
if (nums[i]+nums[left]+nums[right]>0){
right--;
}else if (nums[i]+nums[left]+nums[right]<0){
left++;
}else {
arrayList.add(Arrays.asList(nums[i],nums[left],nums[right]));
while (right>left&&nums[right]==nums[right-1]){
right--;
}
while (right>left&&nums[left]==nums[left+1]){
left++;
}
right--;
left++;
}
}
}
return arrayList;
}
}