题目描述
给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。
注意:答案中不可以包含重复的三元组。
例如, 给定数组 nums = [-1, 0, 1, 2, -1, -4],
满足要求的三元组集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]
我的初步思路:利用穷举法加优化来完成,代码如下:
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> list = new ArrayList<List<Integer>>();
if(nums == null || nums.length<3) {
return list;
}
//1.排序
Arrays.sort(nums);
Set<String> set = new HashSet<String>();
StringBuilder sb = new StringBuilder();
//2.查找匹配项并去重
for(int i=0;i<nums.length-2 && nums[i]<=0;i++) {
for(int j=i+1;j<nums.length-1;j++) {
for(int k=j+1;k<nums.length;k++) {
sb.delete(0, sb.length());
if(nums[i] + nums[j] + nums[k] == 0) {
String tmp = sb.append(nums[i]).append(nums[j]).append(nums[k]).toString();
if(!set.contains(tmp)) {
set.add(tmp);
list.add(Arrays.asList(nums[i], nums[j], nums[k]));
}
}
}
}
}
return list;
}
但是在测试用例输入了一个巨长巨长的数组之后,程序执行时间超出了限制。继续在穷举法上做优化的空间已经不大了。所以考虑使用另一种方法。
改用双指针法,时间勉强达标,代码如下:
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> list = new ArrayList<List<Integer>>();
if(nums == null || nums.length<3) {
return list;
}
//1.排序
Arrays.sort(nums);
Set<String> set = new HashSet<String>();
StringBuilder sb = new StringBuilder();
//2.查找匹配项并去重
for(int i=0;i<nums.length-2 && nums[i]<=0;i++) {
int start =i+1, end = nums.length-1;
while(nums[i]<=0 && start<end) {
if(nums[i] + nums[start] + nums[end] <0) {
start++;
}else if (nums[i] + nums[start] + nums[end] >0) {
end--;
}else {
sb.delete(0, sb.length());
String tmp = sb.append(nums[i]).append(":").append(nums[start]).append(":").append(nums[end]).toString();
if(!set.contains(tmp)) {
set.add(tmp);
list.add(Arrays.asList(nums[i], nums[start], nums[end]));
}
end--;
}
}
}
return list;
}
上面的代码在去重方面明显还有优化空间,翻评论区发现别人的代码,参照优化如下:
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> list = new ArrayList<List<Integer>>();
if(nums == null || nums.length<3) {
return list;
}
//1.排序
Arrays.sort(nums);
//2.查找匹配项并去重
for(int i=0;i<nums.length-2 && nums[i]<=0;i++) {
while (i>0 && i<nums.length-2 && nums[i] == nums[i-1])i++;
int l =i+1, r = nums.length-1, sum=0-nums[i];
while(nums[i]<=0 && l<r) {
if(nums[l] + nums[r] < sum) {
while ((l<r) && nums[l+1] == nums[l])l++;
l++;
}else if (nums[l] + nums[r] >sum) {
while ((l<r) && nums[r-1] == nums[r])r--;
r--;
}else {
list.add(Arrays.asList(nums[i], nums[l], nums[r]));
while ((l<r) && nums[l+1] == nums[l])l++;
while ((l<r) && nums[r-1] == nums[r])r--;
r--;
}
}
}
return list;
}