15. 三数之和 - LeetCode

15. 三数之和

题目链接

枚举+二分

  • 很直接地想到,先排序,枚举前两个数,二分第三个数
class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        Arrays.sort(nums);
        List<List<Integer>> ans = new ArrayList<>();
        int n = nums.length;
        if(n < 3) return ans;
        for(int i = 0; i < n-2; i++){
            if(nums[i] > 0) break;
            if(i > 0 && nums[i] == nums[i-1]) continue;
            for(int j = i+1; j < n-1; j++){
                int sum = nums[i] + nums[j];
                if(sum > 0) break;
                if(j > i+1 && nums[j] == nums[j-1]) continue;
                int k = Arrays.binarySearch(nums, j+1, n, -sum);
                if(k >= 0)
                    ans.add(Arrays.asList(nums[i], nums[j], nums[k]));
            }
        }
        return ans;
    }
}
  • 枚举的过程中,注意以下几点:

    • 第一个数大于0或者前两个数之和大于0,直接break
    • 如果当前的数和上一个数相同,continue
  • 一开始想的是在add的时候判断是否存在这个List,但是会超时,所以选择在二分查找之前判断枚举是否重复

  • 这个算法的时间复杂度是O(N2logN)

枚举+双指针

  • 二分查找第三个数依然太慢了,可以试图找一下规律
  • 显然,排序后,随着j的增大,nums[i]+nums[j]也会增大,那么得到的k一定是减小的
  • 所以我们没必要每次都从头到尾二分查找,直接让k慢慢减小就好了
  • 这样因为k的总共移动次数是O(N),所以第二层循环的时间复杂度也就是O(N),总的时间复杂度就可以达到O(N2)
class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        Arrays.sort(nums);
        List<List<Integer>> ans = new ArrayList<>();
        int n = nums.length;
        if(n < 3) return ans;
        for(int i = 0; i < n-2; i++){
            if(nums[i] > 0) break;
            if(i > 0 && nums[i] == nums[i-1]) continue;
            int k = n-1;
            for(int j = i+1; j < n-1; j++){
                int sum = nums[i] + nums[j];
                if(sum > 0) break;
                if(j > i+1 && nums[j] == nums[j-1]) continue;
                while(k > j && nums[k] + sum > 0) k--;
                if(k == j) break;
                if(nums[k] + sum == 0)
                    ans.add(Arrays.asList(nums[i], nums[j], nums[k]));
                else continue;
            }
        }
        return ans;
    }
}
posted @ 2021-01-28 11:56  一天到晚睡觉的鱼  阅读(70)  评论(0)    收藏  举报