Problem 5 Combination of coins
Method 1一个一个加
each level: 每一层我只拿一个硬币
each branch: 可以选择的硬币&确保不会超过&确保选的是比之前的小
public List<List<Integer>> combinations(int target, int[] coins) {
// sanity check
// initial
List<List<Integer>> result = new ArrayList<>();
if (coins == null || coins.length == 0) {
return result;
}
int[] path = new int[coins.length]; // 因为你需要记录一共这个元素用了多少次,所以需要对该类型的coin进行记录
// dfs
backTracking(result, path, coins, target, 0);
// return
return result;
}
private void backTracking(List<List<Integer>> result, int[] path, int[] coins, int target, int index) {
// base case
if (target == 0) {
addCurrentResult(result, path);
return;
}
// dfs , i代表你拿了谁
for (int i = index; i < coins.length; i++) {
if (target - coins[i] >= 0) {
path[i] += 1;
backTracking(result, path, coins, target - coins[i], i);
path[i] -= 1;
}
}
//
}
Master alter method:
// Some code
Method 2考虑数量
public List<List<Integer>> combinations(int target, int[] coins) {
List<List<Integer>> result = new ArrayList<>();
if (coins == null || coins.length == 0) {
return result;
}
List<Integer> current = new ArrayList<>();
backTracking(result, current, coins, target, 0)l
return result;
}
// index:当前层正在考虑哪种硬币:coins[index]这种
private void backTracking(List<List<Integer>> result, List<Integer> current, int[] coins,int target, int index) {
if (index == coins.length) {
if (target == 0) {
result.add(new ArrayList<>(current));
}
return;
}
// 对于当前层你正在考虑的这种硬币coins[index]你最多拿多少个
int maxNumberUCanTake = target/coins[index];
// 分支:这种硬币你拿几个 range: [0, maxNumberUCanTake]
for(int howManyDidUTake = 0; howManyDidUTake <= maxNumberUCantake; howManyDidUTake++) {
current.add(howManyDidUTake);
backTracking(result, current,coins, target - howManyDidUTake * coins[index], index + 1);
current.remove(current.size() - 1);
}
}
如果用list或者StringBuilder,这里是append不是同一个index赋值操作,所以不能忘记吃吐
老一辈艺术家的写法
// Some code
TC& SC
实际上M1和M2都是在对25a + 10b + 5c + d = 99求解,只是具体的实现不一样
所以这几种算法都是在尝试a&b&c&d的所有可能性
所以这两种做法的复杂度是一样的
从减值的角度看,两种做法都在cur_sum超过target就行了剪枝,是一样优秀的
Last updated