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> combinationSum(int[] candidates,
            int target) {
        ArrayList> ret = new ArrayList>();
        ArrayList solution = new ArrayList();
        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> ret,
            ArrayList solution) {
        if (sum == target) {
            ret.add(new ArrayList(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> result =combinationSum(candidates,7);
            for(int i=0;iout.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的情况。

你可能感兴趣的:(LeetCode)