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 Cunlimited number of times.
Notice
- 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.
Example
Given candidate set [2,3,6,7]
and target 7
, a solution set is:
[7]
[2, 2, 3]
public List<List<Integer>> combinationSum(int[] candidates, int target)
算法:DFS。private void helper(int[] candidates, int target, int idx, int sum, List<Integer> crt, List<List<Integer>> result)
1. 递归定义:用crt容器里现有数字的作为前缀,用candidates里从idx开始的数字作为工具,拼出所有可能得到target的答案,加入到result里
2.递归拆解:for循环试着加入candidates里idx开始的数字,dfs,挪去数字
3.递归出口:在最前面,如果发现到target了,deepcopy进去
细节:
1.记得排序
2.记得去重,这里去重是必须做的。如果前面输入的是[1 2 2 3 4],那你如果想要加一个3就必须要先加两个2了,没有一个2一个3的遍历机会
3.List.toArray() 真的很难用,还是不要用了。会返回一个Object[],而这种又不可以强制类型转换成int[] String[]啊的。唯一方法是用toArray的自带有参重写方法,T[] toArray(T[]),先建好容器再放进去还好,如String[] result = new String[list.size()]; result = list.toArray(result); 以后如果是String[]什么的还是可以用一下的。 但是对本题int[]的不行,因为generic是Integer,要改很多地方很麻烦,这题老老实实for地copy一下。
public class Solution { /* * @param candidates: A list of integers * @param target: An integer * @return: A list of lists of integers */ public List<List<Integer>> combinationSum(int[] candidates, int target) { // write your code here List<List<Integer>> result = new ArrayList<>(); if (candidates == null || candidates.length == 0 || target <= 0) { return result; } // 这里去重是必须做的,否则如果前面输入的是[1 2 2 3 4],那你如果想要加一个3就必须要先加两个2了,没有一个2一个3的遍历机会 int[] candidatesDstct = removeDuplicates(candidates); Arrays.sort(candidatesDstct); helper(candidatesDstct, target, 0, 0, new ArrayList<Integer>(), result); return result; } private void helper(int[] candidates, int target, int idx, int sum, List<Integer> crt, List<List<Integer>> result) { if (sum > target) { return; } if (sum == target) { result.add(new ArrayList<Integer>(crt)); return; } for (int i = idx; i < candidates.length; i++) { crt.add(candidates[i]); helper(candidates, target, i, sum + candidates[i], crt, result); crt.remove(crt.size() - 1); } } private int[] removeDuplicates(int[] arr) { List<Integer> list = new ArrayList<>(); for (int i = 0; i < arr.length; i++) { if (!list.contains(arr[i])) { list.add(arr[i]); } } // toArray()用法的注意,一定要强转类型,默认返回去的是Object[]的。所以一般先建好容器比较好。用重写的方法。 int[] result = new int[list.size()]; for (int i = 0; i < list.size(); i++) { result[i] = list.get(i); } return result; } }