开始刷题,之前几乎没用java写过算法题
这道题是一个典型的"组合总和"问题,属于回溯算法的范畴。
问题类型:
这个问题可以归类为"组合问题",也就是求出所有可能的组合方案。与之相对应的还有排列问题。组合问题的特点是:不关心元素的顺序,只关心最终的组合结果。
算法思路:
这个问题的解决使用了回溯算法(Backtracking)。回溯算法是一种通用的算法思想,它通过不断尝试构造候选解,并在确定该候选解不是最终解的时候回溯,尝试别的可能的候选解。
具体到这个问题,回溯算法的实现步骤如下:
candidates
中选择一个数字,加入到当前组合中。target
。如果是,则将该组合加入到结果集中。candidates
中选择下一个数字,加入到当前组合中。算法复杂度:
candidates
的长度。每个数字都可以选择无限次,因此总共有 2^N 种可能的组合。对于每种组合,我们还需要花费 O(N) 的时间来构造它。总的来说,这是一个典型的回溯算法问题,通过不断尝试构造候选解,并在确定不可行时回溯,最终得到所有可能的组合方案。这种算法思想在许多类似的组合问题中都会用到。
javaclass Solution {
public List<List<Integer>> combinationSum(int[] candidates, int target) {
// 先对 candidates 数组进行排序
Arrays.sort(candidates);
List<List<Integer>> result = new ArrayList<>();
backtrack(result, new ArrayList<>(), candidates, target, 0);
return result;
}
private void backtrack(List<List<Integer>> result, List<Integer> combination, int[] candidates, int remain, int start) {
if (remain < 0) {
return;
} else if (remain == 0) {
result.add(new ArrayList<>(combination));
} else {
for (int i = start; i < candidates.length; i++) {
combination.add(candidates[i]);
backtrack(result, combination, candidates, remain - candidates[i], i);
combination.remove(combination.size() - 1);
}
}
}
}
接下来是相似题目
java
class Solution {
public List<List<Integer>> combine(int n, int k) {
List<List<Integer>> result = new ArrayList<>();
backtrack(result, new ArrayList<>(), n, k, 1);
return result;
}
private void backtrack(List<List<Integer>> result, List<Integer> currentCombination, int n, int k, int start) {
if (currentCombination.size() == k) {
result.add(new ArrayList<>(currentCombination));
return;
}
for (int i = start; i <= n; i++) {
currentCombination.add(i);
backtrack(result, currentCombination, n, k, i + 1);
currentCombination.remove(currentCombination.size() - 1);
}
}
}
javaclass Solution {
public List<List<Integer>> combinationSum3(int k, int n) {
List<List<Integer>> result = new ArrayList<>();
backtrack(result, new ArrayList<>(), k, n, 1);
return result;
}
private void backtrack(List<List<Integer>> result, List<Integer> currentCombination, int k, int n, int start) {
if (currentCombination.size() == k) {
if (getSum(currentCombination) == n) {
result.add(new ArrayList<>(currentCombination));
}
return;
}
for (int i = start; i <= 9; i++) {
currentCombination.add(i);
backtrack(result, currentCombination, k, n, i + 1);
currentCombination.remove(currentCombination.size() - 1);
}
}
private int getSum(List<Integer> combination) {
int sum = 0;
for (int num : combination) {
sum += num;
}
return sum;
}
}
javaclass Solution {
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
// 先对 candidates 数组进行排序
Arrays.sort(candidates);
List<List<Integer>> result = new ArrayList<>();
backtrack(result, new ArrayList<>(), candidates, target, 0);
return result;
}
private void backtrack(List<List<Integer>> result, List<Integer> combination, int[] candidates, int remain, int start) {
if (remain < 0) {
return;
} else if (remain == 0) {
result.add(new ArrayList<>(combination));
} else {
for (int i = start; i < candidates.length; i++) {
if (i > start && candidates[i] == candidates[i - 1]) {
continue; // 跳过重复的数字
}
combination.add(candidates[i]);
backtrack(result, combination, candidates, remain - candidates[i], i + 1);
combination.remove(combination.size() - 1);
}
}
}
}
javaclass Solution {
public int combinationSum4(int[] nums, int target) {
int[] dp = new int[target + 1];
dp[0] = 1; // 当目标值为 0 时,存在一种组合方式
for (int i = 1; i <= target; i++) {
for (int num : nums) {
if (i - num >= 0) {
dp[i] += dp[i - num];
}
}
}
return dp[target];
}
}
javaclass Solution {
public List<List<Integer>> permute(int[] nums) {
List<List<Integer>> result = new ArrayList<>();
backtrack(result, new ArrayList<>(), nums);
return result;
}
private void backtrack(List<List<Integer>> result, List<Integer> currentPermutation, int[] nums) {
if (currentPermutation.size() == nums.length) {
result.add(new ArrayList<>(currentPermutation));
} else {
for (int i = 0; i < nums.length; i++) {
if (currentPermutation.contains(nums[i])) {
continue;
}
currentPermutation.add(nums[i]);
backtrack(result, currentPermutation, nums);
currentPermutation.remove(currentPermutation.size() - 1);
}
}
}
}
本文作者:yowayimono
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!