「这是我参与11月更文挑战的第27天,活动详情查看:2021最后一次更文挑战」
题目描述
给你一个包含 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
题目分析
首先对数组进行排序,使用三个点 i、j 和 k 分别代表要找的三个数。 通过枚举 i 确定第一个数,也就是保证一个点不动,考虑其它两个点的改变,另外两个点 j,k 分别从左边 i + 1 和右边 n - 1 往中间移动,找到满足 nums[i] + nums[j] + nums[k] == 0 的所有组合。 j 和 k 指针的移动逻辑,下面分情况讨论 sum = nums[i] + nums[j] + nums[k] :
- 若和大于0,则右指针自减,k 左移,使 sum 变小
- 若和小于0,则左指针自加,j 右移,使 sum 变大
- 若和等于0,则将三个元素添加至链表中
题目要求答案不能包含重复的三元组,所以在确定第一个数和第二个数的时候,要跳过数值一样的下标。
时间复杂度:O(N^2),其中 N 是数组nums 的长度。
空间复杂度:O(logN)。我们忽略存储答案的空间,额外的排序的空间复杂度为 O(logN)。然而我们修改了输入的数组 nums,在实际情况下不一定允许,因此也可以看成使用了一个额外的数组存储了nums 的副本并进行排序,空间复杂度为 O(N)O(N)。
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
Arrays.sort(nums);
int n = nums.length;
List<List<Integer>> ans = new ArrayList<List<Integer>>();
if(n<3){
return ans;
}
for(int i = 0;i<n-2;i++){
if(i>0 && nums[i] == nums[i-1]) continue;
int j = i+1,k = n-1;
while(j<k){
while(j>i+1 && j<n && nums[j] == nums[j-1]) j++;
if(j>=k){
break;
}
if(nums[i]+nums[j]+nums[k] < 0){
j++;
}else if(nums[i]+nums[j]+nums[k] > 0){
k--;
}else{
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(nums[i]);
list.add(nums[j]);
list.add(nums[k]);
ans.add(list);
j++;
}
}
}
return ans;
}
}
复制代码