LeetCode0015-三数之和
给一个数组,求三个数之和等于0的组合,需要去重.
字节一面面试题。
public class Num015_3sum { //自己写的三指针,没有实现去重功能,没有对初始情况:没有三个数,或者最小值都>0做判断 public List<List<Integer>> threeSum0(int[] nums) { Arrays.sort(nums); int l = nums.length; List<List<Integer>> result = new ArrayList<List<Integer>>(); for (int i = 0; i < l; i++) { int start = i + 1, end = l - 1; while (start < end) { if (nums[i] + nums[start] + nums[end] > 0) { end--; } else if (nums[i] + nums[start] + nums[end] < 0) { start++; } else if (nums[i] + nums[start] + nums[end] == 0) { List<Integer> temp = new ArrayList<Integer>(); temp.add(nums[i]); temp.add(nums[start]); temp.add(nums[end]); result.add(temp); break; } } } return result; }
//参考答案 public List<List<Integer>> threeSum(int[] nums) { List<List<Integer>> result = new ArrayList<List<Integer>>(); if(nums.length<3) return result; Arrays.sort(nums); if(nums[0]>0) return result; for(int i=0;i<nums.length-2;i++){ int target= 0 -nums[i]; // 去重,不会重复针对同样的target进行计算 if(i>0 && nums[i]==nums[i-1]){ // 跳出本次循环继续下一次循环 continue; } int l = i+1; int r = nums.length-1; while(l<r){ if(nums[l]+nums[r]==target){ result.add(new ArrayList<>(Arrays.asList(nums[i],nums[l],nums[r]))); // 如果相邻两个数相等,则继续向下找到不相等的数为止 while(l<r && nums[l]==nums[l+1]) l++; while(l<r && nums[r] == nums[r-1]) r--; l++; r--; }else if(nums[l]+nums[r] >target){ r--; }else { l++; } } } return result; } }
面试时,依然没有写出去重的逻辑,也没有想到小于三的返回 -无语。
然后三刷时,在去重这里想了很久,注意点如下:
public class test { public static List<List<Integer>> threeSum(int[] arr) { Arrays.sort(arr); List<List<Integer>> result = new ArrayList<List<Integer>>(); if (arr.length < 3) return result; if (arr[0] > 0) return result; if (arr[arr.length - 1] < 0) return result;
// 优化点1: 循环到倒数第三个数就可以了 从arr.length - 1 优化到arr.length - 2
for (int i = 0; i < arr.length - 2; i++) {
// 优化点2: 这里避免对同一个target值做重复计算,如【-1,-1,0,1,2】避免输出两个同样针对-1计算的结果
// 此外,用arr[i]==arr[i-1] 而不用 arr[i]== arr[i+1],避免直接跳过了第一个可能,如:【-1,-1,0,1,2】,如果用i+1判断,就会直接跳过了 -1,-1,2这个结果,因为 begin是从 i+1开始计算的
if (i > 0 && arr[i] == arr[i - 1]) { continue; } //优化点3:begin从指定元素之后开始,否则会有很多重复值从1开始 ,这个点也需要与上方的 arr[i-1]配合使用 int begin = i + 1, end = arr.length - 1;
//自己还把单列出了2个while循环,也没有用if else,这块逻辑很受影响。不想分析了 while (begin < end) { if (arr[i] + arr[begin] + arr[end] > 0) { end--; } else if (arr[i] + arr[begin] + arr[end] < 0) { begin++; } else if (arr[i] + arr[begin] + arr[end] == 0) { result.add(new ArrayList<Integer>(Arrays.asList(arr[i], arr[begin], arr[end]))); //只有在相等的时候去去重就可以,不相等的时候不用考虑去重 while (begin < end && arr[end] == arr[end - 1]) end--; while (begin < end && arr[begin] == arr[begin + 1]) begin++; begin++; end--; } } } return result; } public static void main(String[] args) { int[] arr = {0, 0, 0}; List<List<Integer>> result = new ArrayList<List<Integer>>(); result = threeSum(arr); } }