leetcode刷题 39组合总和

题目:

给定一个无重复元素的正整数数组 candidates 和一个正整数 target ,找出 candidates 中所有可以使数字和为目标数 target 的唯一组合。

candidates 中的数字可以无限制重复被选取。如果至少一个所选数字数量不同,则两种组合是唯一的。

思路:这道题思路并不算难,将candidates 从新小到大排序,然后用多个指针同时遍历candidates。假设有n个指针,则先把n个指针都指向candidates[0]。

若此时指针指向的数之和sum==target,就可以把所有指针指向的位置存储起来作为答案。若sum>target,便让最后一个(第n个)指针右移,这样便增大了sum;若sum>target,便放弃对第n个数组的操作,转而让第n-1个指针右移一位, 同时让第n个指针不指向数组。

若此时sum(为前n-1个指针的和,因为第n个指针现在不指向数组),接下来有几种情况:

1.sum==target,此时便可将n-1个指针对应的位置存入res。

2.sum<target,此时重新设置第n个指针,让其和第n-1个指针指向同一个位置,这又会造成几种情况:

        (1)sum==target,所有指针指向的位置存入res

        (2)sum>target,把第n个指针置空,第n-1个指针向右移动一位,重新比较sum与target

        (3)sum<target,将第n个指针右移一位,重新比较sum与target

3.sum>target 此时将第n-1个指针置空,让第n-2个指针右移一位,此时sum为前n-2个指针指向的数字的和,比较sum和target。

之后再依次类推

或许不是表述的很清晰,但思路本身并不难。

/* 
以示例2为例子:
    先对candidates进行排序,假设有l1,l2,l3,l4四个指针(针对不同题目,指针的个数也不同,因为此题答案中最长数组为[2,2,2,2]长度为4,所以指针最多只要4个)
    先将l1指向candidates[0],此时sum=2<target,然后先不移动l1,而是使用第二个指针l2。
    l2指向candidates[0],此时sum=4<target;同理,l3也指向candidates[0],此时sum=6<target;
    最后,将l4指向candidates[0],此时sum=8满足要求,便将四个指针指向的数字存储在res里作为子数列。
    注意:此时我们不用再使用第5个指针了,也不用对l4进行右移操作,因为这样一定会使得sum>target。
    接下来要对的是倒数第二个指针,就是l3进行右移一位的操作,并将l4置空。此时l3指向candidates[1],sum=7<target(sum=candidates[l1]+candidates[l2]+candidates[l3]=7)
    然后再重新设置l4为candidates[1](新设置的指针的初始位置一定和它上一个指针的位置一样,因为之前的位置在前面已经使用过了,这个可以稍微理解下)
    此时,sum=10>target,因此重新将l4置空,然后让l3右移一位指向candidates[2],此时sum=9>target,不合要求。
    再之后,将l3置空,然后让l2右移一位指向candidates[1],此时sum=5<target,因此将l3重新指向和l2一样的位置candidates[1],此时sum=8==target,便可以将l1,l2,l3存到res里
    之后再依次类推,依次将指针不断右移找寻符合条件的情况
*/

    List<List<Integer>> res=new ArrayList<>();
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        Arrays.sort(candidates);
        for (int i = 0; i <candidates.length ; i++) {
            List<Integer> temp=new ArrayList<>();
            temp.add(candidates[i]);
            getRes(candidates,target,candidates[i],i,temp);
        }
        return res;
    }


    private void getRes(int[] candidates, int target, int sum, int position, List<Integer> temp) {
        if (sum==target){
            res.add(new ArrayList<Integer>(temp));
            return;
        }
        int num1=candidates[position];
        List<Integer> temp1=new ArrayList<>(temp);
         if(sum+num1>target){
            return;
        }else {
            while(position<candidates.length && sum+candidates[position]<=target){
                temp1.add(candidates[position]);
                getRes(candidates,target,sum+candidates[position],position,temp1);
                position++;
                temp1.remove(temp1.size()-1);
            }

        }
    }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值