美文网首页
三数之和

三数之和

作者: 二进制的二哈 | 来源:发表于2019-11-29 13:50 被阅读0次

    题目来源:力扣(LeetCode)
    链接:https://leetcode-cn.com/problems/3sum

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

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

    例如:

    给定数组 nums = [-1, 0, 1, 2, -1, -4],
    满足要求的三元组集合为:
    [
      [-1, 0, 1],
      [-1, -1, 2]
    ]
    

    1.暴力解法,遍历数组,再以寻找两数之和的方式,最后对结果去重。

    执行用时 :637 ms, 在所有 java 提交中击败了5.01%的用户
    内存消耗 :54.8 MB, 在所有 java 提交中击败了76.14%的用户
    Java代码:

    class Solution {
        public List<List<Integer>> threeSum(int[] nums) {
            List<List<Integer>> res = new ArrayList<>();
            Map<String,Integer> map = new HashMap<>();
            for(int i = 0;i<nums.length;i++){
                if(map.get(nums[i]+"") == null){
                    List<List<Integer>> tmp = twoNum(nums,i);
                    if(tmp.size() > 0){
                        for(List<Integer> list : tmp){
                            String key = list.get(0) + "-" +  list.get(1) + "-"+list.get(2);
                            if(map.get(key) == null){
                                res.add(list);
                            }
                            map.put(key,1);
                        }     
                    }
                }
                map.put(nums[i]+"",1);
            }
            return res;
        }
    
        private List<List<Integer>> twoNum(int[] nums,int curIndex){
            List<List<Integer>> res = new ArrayList<>();
            int curNum = nums[curIndex];
            int target = 0-curNum;
            Map<Integer,Integer> map = new HashMap<>();
            //找出两数之和=target的数
            for(int i = 0;i<nums.length;i++){
                if(i != curIndex){
                    int tmp = nums[i];
                    int diff = target - tmp;
                    Integer isExist = map.get(tmp);
                    if(isExist != null){
                        //这两数之和 = target
                        List<Integer> tmpList = new ArrayList<>();
                        //存的时候从小到大
                        int exists = nums[isExist];
                        tmpList.add(tmp);
                        tmpList.add(exists);
                        tmpList.add(curNum);
                        Collections.sort(tmpList);
                        res.add(tmpList);
                    }else{
                        map.put(diff,i);
                    }
                }
            }
            return res;
        }
    }
    

    2.排序+双指针解法

    Java代码:

    class Solution {
        public List<List<Integer>> threeSum(int[] nums) {
            List<List<Integer>> res = new ArrayList<>();
            if(nums != null && nums.length > 2){
                //对数组排序
                Arrays.sort(nums);//[-4,-1,-1,0,1,2]
                for(int i = 0;i<nums.length - 1;i++){
                    int curNum = nums[i];
                    if(curNum > 0)
                        break;
                    if(i > 0 && nums[i] == nums[i-1])//这一步也是去重
                        continue;
                    int left = i+1;
                    int right = nums.length - 1;
                    while(left < right){
                        int sum = curNum + nums[left] + nums[right];
                        if(sum == 0){
                            List<Integer> tmpList = new ArrayList<>();
                            tmpList.add(curNum);
                            tmpList.add(nums[left]);
                            tmpList.add(nums[right]);
                            res.add(tmpList);
                            //left向后找,如果数一样,就向后移动,达到去重的目的
                            while(left < right && nums[left] == nums[left+1]){
                                left++;
                            }
                            //right向前,如果数一样,就向前移动
                            while(left < right && nums[right] == nums[right-1]){
                                right--;
                            }
                            left++;
                            right--;
                        }else if(sum < 0){
                            //总和小于0,说明left的值太小了,left指针向右移动
                            left++;
                        }else{
                            //总和大于0,说明right的值太大了,right指针向左移动
                            right--;
                        }
                    }
                }
            }
            return res;
        }
    }
    

    相关文章

      网友评论

          本文标题:三数之和

          本文链接:https://www.haomeiwen.com/subject/sxxgwctx.html