LeetCode刷题之路 3Sum

17 篇文章 0 订阅
17 篇文章 0 订阅

3Sum

Given an array nums of n integers, are there elements abc in nums such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.

Note:

The solution set must not contain duplicate triplets.

Example:

Given array nums = [-1, 0, 1, 2, -1, -4],

A solution set is:
[
  [-1, 0, 1],
  [-1, -1, 2]
]
3 Sum, two sum 进阶问题,看到题目第一想法就是把这个转化成2 sum 类型,也就是说先fix一个数,然后在数组寻找俩个数的合为负的fix的这个数。在套用2 sum的算法时候发现会产生很多的重复解。于是又对这些解每次插入到结果前先排序,确保如果有重复解,解的样子一致。最后在输出结果的时候利用hashset去除重复解。但是最后超时。。

public class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> result = new ArrayList<>();
        if(nums.length < 3) return result;

        for(int temp = 0; temp < nums.length; temp++){
            HashMap<Integer,Integer> map = new HashMap<>();
            for(int i = nums.length-1; i>=0; i--){
                if(i != temp){
                    int complete = 0 - nums[temp] - nums[i];
                    if(map.containsKey(complete)){
                        int[] input = new int[]{nums[i], nums[temp], complete};
                        Arrays.sort(input); // 排序确保解的形式一致
                        result.add(Arrays.asList(input[0], input[1], input[2]));
                    }
                    map.put(nums[i], i);
                }
            }
        }
        HashSet h = new HashSet(result); //去除重复解
        result.clear();
        result.addAll(h);
        return result;
    }
}

这种方法不行的话,所以我考虑像另外一道two sum一样,采用two pointer, 不过需要先要把数组排列一下。

因为现在的数组是排列好的,所以我们可以做个剪枝优化,即每次优先判断fix的那个数是否是大于0,如果大于0就不用往下循环,因为后面数都肯定大于0,结果不可能为0。然后我们需要考虑一个去除重复问题。由于数组已经排列好,重复解应该是重复fix了同一个数才产生, 所以只要每次判断是否当前fix数的值等于上一个fix数的值就能去除重复解。

public class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> result = new ArrayList<>();
        if(nums.length<3){
            return result;
        }
        Arrays.sort(nums);
        for(int fix = 0; fix < nums.length-2; fix++){
            if(nums[fix] > 0){
                break;
            }
            if (fix != 0 && nums[fix] == nums[fix - 1]) continue;
            int start = fix + 1;
            int end = nums.length -1;
            int sum = 0 - nums[fix];
            while(start < end){
                int temp = nums[start] + nums[end];
                if(temp == sum){
                    result.add(Arrays.asList(nums[fix], nums[start], nums[end]));
                     while((end-1)>=start && nums[end] == nums[--end]);
                }
                if(temp < sum){
                    start++;
                }
                if(temp > sum) {
                    end--;
                }
            }
        }
        return result;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值