码迷,mamicode.com
首页 > 其他好文 > 详细

三数之和

时间:2021-06-08 23:03:35      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:哈希表   出现   组合   etc   get   元素   --   add   重复   

三数之和题目入口
方法一:暴力法,三重for循环,枚举所有的三数组合,时间复杂度为O(\(n^3\)),因为时间复杂度过高,已经TLE了,所以对结果集不作去重处理了,此方法不可以通过

public List<List<Integer>> threeSum(int[] nums) {
        int len = nums.length;
        //提前定义结果列表
        ArrayList<List<Integer>> result = new ArrayList<>();
        for(int i = 0; i < len - 2; i++){
            for(int j = i + 1; j < len - 1; j++){
                for(int k = j + 1; k < len; k++){
                    if(nums[i] + nums[j] + nums[k] == 0){
                        result.add(Arrays.asList(nums[i] , nums[j] , nums[k]));
                    }
                }
            }
        }
        return result;
}

方法二:用哈希表保存结果,时间复杂度为O(\(n^2\)),用到的数据结构过于复杂,去重和保存不同两数和的问题也没有解决,此方法不可以通过

public List<List<Integer>> threeSum(int[] nums) {
        int len = nums.length;
        //提前定义结果列表
        ArrayList<List<Integer>> result = new ArrayList<>();
        //定义一个哈希表
        HashMap<Integer, List<Integer>> hashMap = new HashMap<>();
        for(int i = 0; i < len; i++){
            int thatNum = 0 - nums[i];
            if(hashMap.containsKey(thatNum)){
                //如果已经存在thatNum,则找到了一组解
                ArrayList<Integer> tempList = new ArrayList<>(hashMap.get(thatNum));
                tempList.add(nums[i]);
                result.add(tempList);
            }
            //把当前数对应的两数组合保存到map里
            for(int j = 0; j < i; j++){
                //以两数之和作为当前的关键字
                int newKey = nums[i] + nums[j];
                //如果key不存在,就直接添加进去
                if(!hashMap.containsKey(newKey)){
                    ArrayList<Integer> tempList = new ArrayList<>();
                    tempList.add(nums[i]);
                    tempList.add(nums[j]);
                    hashMap.put(newKey , tempList);
                }
            }
        }
        return result;
}

方法三:双指针法,时间复杂度为O(\(n^2\)),此方法可以通过
(1)对nums数组进行排序,数字求和跟每个数的大小是有关系的,如果先对数组排序,那后面就会容易很多,这一步的时间复杂度为O(\(nlogn\)),"-1 0 1 2 -1 4"排序后的结果为"-4 -1 -1 0 1 2";
(2)然后定义左右指针L喝R,并以指针i遍历数组元素,固定3个指针中最左的指针i,双指针L,R分别在数组索引(i,len(nums))两端,所以初始值i=0,L=i+1,R=nums.length-1
技术图片
令sum=nums[i]+nums[L]+nums[R],如果sum<0,L++并跳过所有重复的nums[L],如果L一直右移,直到跟R重合,那么i++,换一个数考虑,总而言之,L和R只要撞在一起,就i++。

public List<List<Integer>> threeSum(int[] nums) {
        int len = nums.length;
        //提前定义结果列表
        ArrayList<List<Integer>> result = new ArrayList<>();
        Arrays.sort(nums);
        //1.遍历每一个数,作为当前三元组最小的那一个数
        for(int i = 0; i < len; i++){
            //如果当前数已经大于0,直接退出循环
            if(nums[i] > 0) break;
            //如果当前数据已经出现过,直接跳过
            if(i > 0 && nums[i] == nums[i - 1] ) continue;
            //常规情况,以当前情况作为最小数,定义L,R指针
            int L = i + 1;
            int R = len - 1;
            //只要两个指针不相撞,就继续移动指针
            while(L < R){
                int sum = nums[i] + nums[L] + nums[R];
                //判断sum,与0作大小对比
                if(sum == 0){
                    //找到了一组解,然后继续进行匹配
                    result.add(Arrays.asList(nums[i] , nums[L] , nums[R]));
                    L++;
                    R--;
                    //如果移动之后的元素相同,直接跳过
                    while(L < R && nums[L] == nums[L - 1]) L++;
                    while(L < R && nums[R] == nums[R + 1]) R--;
                }else if(sum < 0){//较小的数增大,左指针右移
                    L++;
                }else{//较大的数减小,右指针左移
                    R--;
                }
            }
        }
        return result;
}

三数之和

标签:哈希表   出现   组合   etc   get   元素   --   add   重复   

原文地址:https://www.cnblogs.com/xbdcjs/p/14861134.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!