题目描述:
给定一个无重复元素的数组 candidates和一个目标数 target,找出 candidates中所有可以使数字和为 target的组合。
candidates中的数字可以无限制重复被选取。
说明:
- 所有数字(包括 target)都是正整数。
- 解集不能包含重复的组合。
示例1:
输入: candidates = [2,3,6,7], target = 7, 所求解集为: [ [7], [2,2,3] ]
示例2:
输入: candidates = [2,3,5], target = 8, 所求解集为: [ [2,2,2,2], [2,3,3], [3,5] ]
题目难度:中等
分析:
此题需要穷举出所有的结果去判断是否符合题意,拿示例二来说,第0个元素是2,那么需要一直判断2+2+2+2+2…是否等于8,只要结果小于8那么就一直加下去,如果等于8,那么加入结果集,如果大于8了,说明不符合题意了,此时把最后一个2去掉,再把3放入,继续判断,以此类推。
代码如下:
class Solution { public List<List<Integer>> combinationSum(int[] candidates, int target) { // 最终返回结果 List<List<Integer>> res = new ArrayList<>(); // 结果中的List,用来记录单个数字 List<Integer> list = new ArrayList<>(); // 如果数字为空,直接返回 if (candidates.length == 0) { return new ArrayList<>(); } // 递归方法,用来穷举出所有结果 combinationSumHelp(res, list, candidates, target, 0); return res; } /** * @param res 最终结果集合 * @param list 结果中的数字集合 * @param candidates 数组 * @param target 目标数字 * @param start 开始的下标 */ private void combinationSumHelp(List<List<Integer>> res, List<Integer> list, int[] candidates, int target, int start) { // 递归结束的条件:当目标数等于0时说明找到了一组集合 if (target == 0) { List<Integer> temp = new ArrayList<>(list); res.add(temp); // 目标数只要大于0就说明还需要继续寻找是否有元素可以匹配,小于0时就说明不存在 } else if (target > 0) { // 从开始位置遍历数组,把每一个元素都加入集合中去穷举结果 for (int i = start; i < candidates.length; i++) { list.add(candidates[i]); // 每加入一个元素,那么target就应该减去这个数,同时开始下标也要变 combinationSumHelp(res, list, candidates, target - candidates[i], i); // remove掉最后一个元素,接着递归 list.remove(list.size() - 1); } } } }
总结:
像此类需要穷举结果集的一般都是用递归,比较简单,缺点就是时间复杂度比较高,并且不好计算(一般递归题,我都不说明时间复杂度。/手动滑稽),注意递归的结束条件即可。