Leetcode 之 twoSum, ThreeSum, FourSum(K-Sum)问题

在leetcode里有一类题目,可以统称为K Sum 问题,大意就是:给出一个数组,一个目标值,要求你找出这个数组中所有的组合,满足:这k个数的组合之和为target值。

举个栗子(four sum):
given array S = {1 0 -1 0 -2 2}, and target = 0.

A solution set is:
(-1,  0, 0, 1)
(-2, -1, 1, 2)
(-2,  0, 0, 2)

其实所有的解法都可以从twosum得出,先给出twosum的解法:
1. 先给数组nums排序;
2. 放两个指针,一个在数组头,一个在数组尾部;
3. 判断两数之和是否为target,如果是,保存此组合;
4. 如果不是
i: 小于target,头指针往尾部方向移动一格;
ii.大于target,尾部指针往头部方向移动一格;

为了避免麻烦的重复答案的讨论,我用来一个HashSet,来保证最终结果的唯一性。

注意:HashSet 可以判断List在set中的唯一性,却无法判断int[]在set中的唯一性。所以代码中如果把temp设为了int[], 则结果会出现重复的问题。

twosome代码如下:

public List<List<Integer>>twoSum(int[]nums,int target){
        List <List<Integer>>L=new ArrayList<List<Integer>>();
        List<Integer>l;
        Arrays.sort(nums);
        HashSet<List<Integer>>result=new HashSet<List<Integer>>();
        List<Integer>temp;
        int i=0,j=nums.length-1;

        while(i<j){
            if(nums[i]+nums[j]==target){
                temp=new ArrayList<Integer>();
                temp.add(nums[i]);
                temp.add(nums[j]);
                if(!result.contains(temp)){
                result.add(temp);
                L.add(temp);
                }
                i++;
                j--;
            }
            else if(nums[i]+nums[j]<target)
                i++;
            else j--;
        }


        return L;}

threeSum 和 fourSum的方法就是多几层循环,也就是先把最开头的几个数定了,比如three Sum中,先定好第一个数,就讲此问题退化成了一个twoSum的问题。

但要注意的是:如果想保证所耗时间尽可能的少,还需在头指针加入一个判断,判断此头指针之前有没有已经讨论过了

ThreeSum代码如下:

public List<List<Integer>>threeSum(int[]nums,int target){
        List <List<Integer>>L=new ArrayList<List<Integer>>();
        List<Integer>l;
        List<Integer>temp;
        HashSet<List<Integer>>result=new HashSet<List<Integer>>();
        int j,k;
        Arrays.sort(nums);
        for(int i=0;i<nums.length-2;i++){
            if(i!=0&&nums[i]==nums[i-1])continue;
            j=i+1;
            k=nums.length-1;
            while(j<k){

                if(nums[i]+nums[j]+nums[k]==target){
//                  System.out.println("find one");
                    temp=new ArrayList<Integer>();
                    temp.add(nums[i]);
                    temp.add(nums[j]);
                    temp.add(nums[k]);
                    if(!result.contains(temp)){
                    result.add(temp);
                    L.add(temp);}
                    j++;
                    k--;
                }
                else if(nums[i]+nums[j]+nums[k]<target){
                    j++;
                }
                else k--;
            }
        }


        return L;
    }

FourSum代码如下:

public List<List<Integer>> fourSum(int[] nums, int target) {
        List <List<Integer>>L=new ArrayList<List<Integer>>();
        List<Integer>l;
        Arrays.sort(nums);
        int k,w;
        ArrayList<Integer>temp;
        HashSet<List<Integer>>result=new HashSet<List<Integer>>();
        for(int i=0;i<nums.length-3;i++){
            if(i!=0&&nums[i]==nums[i-1])continue;
            for(int j=i+1;j<nums.length-2;j++){
                if(j!=i+1&&nums[j]==nums[j-1])continue;
//              System.out.println("ff");
                k=j+1;
                w=nums.length-1;

                while(k<w){
                    if(nums[i]+nums[j]+nums[k]+nums[w]==target){

                        temp=new ArrayList<Integer>();
                        temp.add(nums[i]);
                        temp.add(nums[j]);
                        temp.add(nums[k]);
                        temp.add(nums[w]);
                        if(!result.contains(temp)){
                        result.add(temp);
                        L.add(temp);}
                        k++;
                        w--;
                    }
                    else if(nums[i]+nums[j]+nums[k]+nums[w]<target){
                        k++;
                    }
                    else w--;

                }
            }
        }


        return L;

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值