思路
三重循环判断
- 需要进行特判
- 对于长度不够3的可以直接返回空
首先最简单的思路就是三重循环(i,j,k)
for i:
for j:
for k:
if(nums[i]+nums[j]+nums[k]==0)
但答案要求去重,可以通过contains()
函数来完成
if (!res.contains(ans)) {
res.add(ans);
}
优化
- 对于去重,
- 我们考虑其本质:比如对
i
层进行搜索时,对于nums[i]
,已经将后面的所有可能性搜索完毕,那么当后面出现与nums[i]
相同的数字,就可以不对其进行搜索完成去重。j
层同理。
- 我们考虑其本质:比如对
Arrays.sort(nums)
for (i = 0; i < n; i ++)
//去重判断
if(i > 0 && nums[i] == nums[i-1]) continue;
- 对于
k
层循环- 将数组排序后,
a = nums[i]
和b = nums[j]
,查找c
时,可以从末尾递减查询 - 因为
a + b + c = 0
,当b
增大时,c
需要满足减小,意思是j
层循环和k
层循环为并列关系,从而将时间复杂度缩减为O(N^2)
- 将数组排序后,
int n = nums.length - 1
for i:
int k = n - 1
for j:
while(j < k && a + b + c > 0)
k --
完整代码
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> res = new ArrayList<>();
if (nums.length < 3) {
return res;
}
Arrays.sort(nums);
for (int i = 0; i < nums.length; i++) {
if (i > 0 && nums[i] == nums[i - 1]) continue;
int k = nums.length - 1;
for (int j = i + 1; j < nums.length; j++) {
if ((j > i+1 && nums[j] == nums[j - 1]) || nums[i] + nums[j] + nums[nums.length - 1] < 0) {
continue;
}
while (j < k && nums[i] + nums[j] > -nums[k]) {
k--;
}
//当j==k时,需退出循环
if (k == j) continue;
if (nums[i] + nums[j] == -nums[k]) {
List<Integer> ans = new ArrayList<>();
ans.add(nums[i]);
ans.add(nums[j]);
ans.add(nums[k]);
res.add(ans);
}
}
}
return res;
}
}