题目描述:
Given an array S of n integers, are there elements a, b,c in S such that a + b + c = 0? Find all unique triplets in the array whichgives the sum of zero.
Note: The solution set must not contain duplicatetriplets.
For example, given arrayS = [-1, 0, 1, 2, -1, -4],
A solution set is:
[ [-1, 0, 1],[-1, -1, 2]]
给定n个整数组成的Array,是否这n个整数中存在a+b+c==0,如果存在则输三元组[a,b,c];三元组[a,b,c]不能重复即保证三元组是唯一的;三元组[a,b,c]不能降序排列。
测试用例:
1. 功能测试:S = [-1, 0, 1, 2, -1, -4],全0,全1;
2. 边界测试:S中的整数个数小于3
3. 错误测试:S是null
分析:
1. 用三重循环,时间复杂度太高,要思考其他的方法;
2. 先将S排序;
3. 数字a从S[0]到S[n-2]开始循环:
4. 保证a不重复,即a不等与它前面一个数字S[i]!=S[i-1]
5. 设置lo、hi指针,lo从a的后面以为开始,hi从数组最末尾开始;
6. 判断a+S[lo]+S[hi]是否等于0,如果等于0则,则找到一组数字,将指针lo向后移动,将hi向前移动;
7. 如果S[lo]+S[hi]<-a,则lo往后移动
8. 如果S[lo]+S[hi]>-a,则hi往前移动
9. 直到lo>=hi时,不再移动lo和hi指针,a取下一个数字开始下一轮计算
10. 容易出错的地方在于如何保证b,c不重复:在找到一组数字后,移动lo和hi,跳过相同的S[lo]和S[hi];没有找到一组数字,移动lo后,判断是否与之前的相同,跳过相同的S[lo],移动hi后,判断是否与之前的相同,要跳过相同的S[hi]
11. 跳过相同的数字代码:while (lo< hi && nums[lo] == nums[lo -
1]) lo++;
while (lo< hi && nums[hi] == nums[hi +
1]) hi--;
要注意这两行代码的位置
我的解答:
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> ans =new ArrayList<>();
if (nums.length < 3) return ans;
Arrays.sort(nums);
for(int i = 0;i < nums.length - 2; i++) {
if (nums[i]> 0){
return ans;
}
if (i> 0 &&nums[i] == nums[i - 1]) continue;
int target= -nums[i];
int lo = i+ 1,hi = nums.length - 1;
while (lo< hi) {
if (nums[lo]+ nums[hi] == target) {
ans.add(Arrays.asList(nums[i],nums[lo], nums[hi]));
lo++;
hi--;
while (lo < hi && nums[lo] == nums[lo - 1])lo++;
while (lo < hi && nums[hi] == nums[hi + 1])hi--;
}
else if (nums[lo]+ nums[hi] < target) {
lo++;
while (lo < hi && nums[lo] == nums[lo - 1])lo++;
}
else {
hi--;
while (lo < hi && nums[hi] == nums[hi + 1])hi--;
}
}
}
return ans;
}