经典的多数字之和问题,普通的三层循环暴力拆解遇到长数组时的时间复杂度肯定超标,这里还是采用经典的双指针法,先对数组进行排序,再移动指针进行判断
// 三数之和
public List<List<Integer>> threeSum(int[] nums) {
// 结果
List<List<Integer>> resultList=new ArrayList<>();
// 将结果拼接成字符串,去重用
List<String> fifter=new ArrayList<>();
// 排序
Arrays.sort(nums);
StringBuilder sb=new StringBuilder();
// 一层遍历取第一个数
for(int i=0;i< nums.length-2;i++){
// 由于是排序后的,如果第一个数都大于0,后面的数肯定也大于0直接跳过
if(nums[i]>0){
continue;
}
// 第二个数从第一个数的后面开始取
int begin=i+1;
// 第三个从最后一个开始取
int end= nums.length-1;
// 给出初始条件,防止指针相撞
while(end>begin){
if(nums[i]+nums[begin]+nums[end]>0){
// 结果过大,将后指针前移,以缩小结果,用do while跳过重复项
do{
end--;
}while(nums[end+1]==nums[end]&&end>begin);
}else if(nums[i]+nums[begin]+nums[end]<0){
// 结果过小,将前指针后移
do{
begin++;
}while(nums[begin-1]==nums[begin]&&end>begin);
}else{
// 符合,去重
sb.setLength(0);
sb.append(nums[i]).append(",").append(nums[begin]).append(",").append(nums[end]);
if(!fifter.contains(sb.toString())){
// 放入结果
resultList.add(Arrays.asList(new Integer[]{nums[i],nums[begin],nums[end]}));
// 加入去重集合
fifter.add(sb.toString());
}
// 不管是否重复,都必须继续移动指针,不然死循环
do{
begin++;
}while(nums[begin-1]==nums[begin]&&end>begin);
do{
end--;
}while(nums[end+1]==nums[end]&&end>begin);
}
// 检查指针是否相撞
if(begin>=end){
break;
}
}
}
return resultList;
}
这是我的写法,才超过了百分之5的解法,有没有大佬能看出来问题主要出在哪,欢迎指正。