本文已参与「新人创作礼」活动,一起开启掘金创作之路。
1.题目描述
给你一个包含 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
2.解法:排序 + 双指针
这道题和Leetcode 1.两数之和一个概念,该题相当于两数之和的进阶版。 但两数之和因为只有两个数,所以可以通过哈希表来减少一层循环。但本题是三个数,所以哈希表不好用。
2.1 思路
这道题的难点在需要排除重复的数,就不能用枚举法,而且判定的时候麻烦了许多。
- 首先为了便于排除重复的数,就先将数组排序。
因为排序之后顺序是从小到大的,所以最左边的就是最小的,最右边的就是最大的。
-
排除最小的值nums[left]都大于0的情况。
-
之后将重复的nums[left]值去掉。
-
最后while进行双指针的判断,如果三数之和为0放进答案,为了防止有重复的答案,所以重复的nums[left]和nums[right]的值就跳过;如果三数之和大于0,则说明right太大了;如果三数之和小于0,则说明left太小了。分别移动。
最后遍历结束就可以返回答案了。
2.2 Java代码
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> ans = new ArrayList<>();
int len = nums.length;
Arrays.sort(nums);
for(int left = 0;left <len;left++){
if(nums[left]>0){
return ans;
}
if(left>0 && nums[left] == nums[left-1]){
continue;
}
int mid = left+1,right = len-1;
while(mid<right){
if(nums[left]+nums[mid]+nums[right] == 0){
List<Integer> temp = new ArrayList<>();
temp.add(nums[left]);
temp.add(nums[mid]);
temp.add(nums[right]);
ans.add(temp);
while(mid<right&&nums[mid]==nums[mid+1]){
mid++;
}
while(mid<right&&nums[right]==nums[right-1]){
right--;
}
mid++;
right--;
}
else if(nums[left]+nums[mid]+nums[right] < 0){
mid++;
}
else{
right--;
}
}
}
return ans;
}
}
复制代码