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); } }

 

posted on 2021-06-30 10:22  cStream  阅读(50)  评论(0)    收藏  举报