• LeetCode No15. 三数之和


    题目

    给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。

    注意:答案中不可以包含重复的三元组。

    示例 1:

    输入:nums = [-1,0,1,2,-1,-4]
    输出:[[-1,-1,2],[-1,0,1]]

    示例 2:

    输入:nums = []
    输出:[]

    示例 3:

    输入:nums = [0]
    输出:[]

    思路

    首先第一反应就是暴力,三重循环,然后时间复杂度O(n^3),按照题目给的数据范围应该不会超时,然而写完之后提交直接超时。那就优化呗,看题目的样例,似乎是对返回的顺序什么的没有要求,那么就想到排序,然后对排序后的数组去取值,这样就想到如下两种方法:

    二分查找

    既然三重循环不行,那我减少一层循环试试,先用两层循环找到两个数a、b,因为需要三个数之和为0,那么另外一个数必然是 -(a+b),因为数组已经有序,找这个数就可以用二分,时间复杂度为O(n^2*log(n))。

    双指针

    既然已经能减少一层循环,那么是否还能再减少一层循环呢?显然是可以的,用一层循环遍历出第一个数a,对于剩下的两个数,由于数组已经排好序了,只需要用两个指针去从数组的头和尾取数,只要找到的两个数和a相加等0即可。

    AC代码

    二分查找

    点击查看代码
    class Solution {
    
        private int b_search(int[] nums, int low, int high, int num) {
            while( low <= high ) {
                int mid = ( low + high ) / 2;
                if( nums[mid] == num ) {
                    return mid;
                } else if( nums[mid] > num ){
                    high = mid - 1;
                } else {
                    low = mid + 1;
                }
            }
            return -1;
        }
    
        public List<List<Integer>> threeSum(int[] nums) {
            List<List<Integer>> res = new ArrayList<>();
            int len = nums.length;
            if( len < 3 ){
                return res;
            }
            Arrays.sort(nums);
            for(int i=0; i<len; i++) {
                if( i!=0 && nums[i-1]==nums[i] ) {
                    continue;
                }
                int last = i+1;
                while( last < len-1 ) {
                    if( last > i+1 && nums[last-1]==nums[last] ) {
                        last ++;
                        continue;
                    }
                    int num = nums[i] + nums[last];
                    if( num > 0 ) {
                        break;
                    }
                    int ind = b_search(nums, last+1, len-1, num*-1);
                    if( ind!=-1 ) {
                        List<Integer> list = new ArrayList<>();
                        list.add(nums[i]);
                        list.add(nums[last]);
                        list.add(nums[ind]);
                        res.add(list);
                    }
                    last ++;
                }
            }
            return res;
        }
    }
    

    双指针

    点击查看代码
    class Solution {
        public List<List<Integer>> threeSum(int[] nums) {
            List<List<Integer>> res = new ArrayList<>();
            int lasta = -100005;
            int n = nums.length;
            Arrays.sort(nums);
            for(int i=0; i<n; i++) {
                int a = nums[i];
                if( lasta==a ) {
                    continue;
                }
                lasta = a;
                int low = i+1;
                int high = n - 1;
                while( low < high ) {
                    int sum = a + nums[low] + nums[high];
                    if( sum>0 ) {
                        high --;
                    } else if( sum < 0 ) {
                        low ++;
                    } else {
                        List<Integer> list = new ArrayList<>();
                        list.add(a);
                        list.add(nums[low]);
                        list.add(nums[high]);
                        res.add(list);
                        while(low<high && nums[low]==nums[low+1]) {
                            low ++;
                        }
                        while(low<high && nums[high]==nums[high-1]) {
                            high --;
                        }
                        low ++;
                        high --;
                    }
                }
            }
            return res;
        }
    }
    
  • 相关阅读:
    java-5
    java-4
    java-03
    java-02
    Java的集合类
    数据库之约束
    网络编程
    多表查询
    二维数组打印乘法表,三角形,输入三个数,输出最大值
    例:进店买衣服案例
  • 原文地址:https://www.cnblogs.com/Asimple/p/16171779.html
Copyright © 2020-2023  润新知