LeetCode之求组合数之和CombinationSum

问题描述:

/**
 * Given a set of candidate numbers (C) and a target number (T), find all unique
 * combinations in C where the candidate numbers sums to T.
 * 
 * The same repeated number may be chosen from C unlimited number of times.
 * 
 * Note:
 * 
 * All numbers (including target) will be positive integers.
 * 
 * Elements in a combination (a1, a2, ... , ak) must be in non-descending order.
 * (ie, a1 <= a2 <= ... <= ak).
 * 
 * The solution set must not contain duplicate combinations. For example, given
 * candidate set 2,3,6,7 and target 7, A solution set is: [7] [2, 2, 3]
 */

给一组数,和一个目标和,求有几种组合可以到达目标和。给的这组数要为升序排列。而且这组数里面的数可以使用多次。但是不允许有重复的组合出现。具体代码如下:

public static ArrayList<ArrayList<Integer>> combinationSum(int[] candidates,
            int target) {
        ArrayList<ArrayList<Integer>> ret = new ArrayList<ArrayList<Integer>>();
        ArrayList<Integer> solution = new ArrayList<Integer>();
        Arrays.sort(candidates);
        combinationSum(candidates, 0, 0, target, ret, solution);
        return ret;
    }

    private static void combinationSum(int[] candidates, int start, int sum,
            int target, ArrayList<ArrayList<Integer>> ret,
            ArrayList<Integer> solution) {
        if (sum == target) {
            ret.add(new ArrayList<Integer>(solution));
            return;
        }
        if (sum > target)
            return;
        for (int i = start; i < candidates.length; i++) {
            solution.add(candidates[i]);
            combinationSum(candidates, i, sum + candidates[i], target, ret, solution);
            solution.remove(solution.size() - 1);
        }
    }
    //测试代码
        public static void main(String args[])
        {
            int[]candidates = new int[]{2,3,6,7};
            ArrayList<ArrayList<Integer>> result =combinationSum(candidates,7);
            for(int i=0;i<result.size();i++)
            {
                System.out.print(result.get(i));
            }
        }

老规矩,二维数组ret存储结果组合。一维数组result存储结果。
首先对给的数组进行了sort排序,保证非递减排列。
然后在combinationSum()方法中,首先判断得到的和是否等于target,相等,则把结果存储到ret数组中,然后return到for循环中,把result数组的最后一个删除掉,遍历下一个数。
在for循环中,还运用了一次递归。这个在每次结束这一层递归的时候都会从for循环的开始进行,要注意这一点,在调试的时候可以发现,其实这一点容易搞晕。

因为每次在for循环中进入递归,所以每次刚进入递归时都是从开头i=0开始循环的,所以刚开始会有[2,2,2,2]这种情况,然后会把最后一位remove掉因为(其和为8,大于target,要return回去),变为[2,2,2],然后再进行下一次for循环,这次循环就从i=1开始,result数组开始为,[2,2,2,3],[2,2,2,6],[2,2,2,7].注意,这时,这层递归的for循环已经执行完毕,所以要跳出这层递归,再进行新的一轮for循环。然后result就变为,[2,2,2],[2,2,3],[2,2,6],[2,2,7].在这期间,如果有符合条件的就会存储到ret数组中。依次类推。
理解这个for循环+递归,大致是这样的:

result数组格式:[x,x,x,x]
[x1,x2,x3,x4]这是第四层递归,也就是说最里层的,在这一层中,会把x4 for循环一遍来找到合适的组合。
[x1,x2,x3]是第三层递归。x3会被循环一遍
[x1,x2]是第二层递归,x2会被循环一遍
[x1]是最外层的,x1会被循环一遍

每次要跳出这层递归时会连续删除两次的末尾数据,这个在调试时容易搞晕,因为在for循环时会把最后一个remove掉(便于遍历下一个数据),然后跳出这层递归时,会删减一个数字。所以会出现连续两次remove的情况。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值