回溯算法是⼀种经典的递归算法,通常⽤于解决组合问题、排列问题和搜索问题等。
回溯算法的基本思想:从⼀个初始状态开始,按照⼀定的规则向前搜索,当搜索到某个状态⽆法前进 时,回退到前⼀个状态,再按照其他的规则搜索。
回溯算法在搜索过程中维护⼀个状态树,通过遍历 状态树来实现对所有可能解的搜索。 回溯算法的核⼼思想:“试错”,即在搜索过程中不断地做出选择,如果选择正确,则继续向前搜 索;否则,回退到上⼀个状态,重新做出选择。
回溯算法通常⽤于解决具有多个解,且每个解都需要 搜索才能找到的问题。
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Backtracking {
public void backtracking(int[] candidates, int target) {
List> result = new ArrayList<>();
Arrays.sort(candidates);
// 如果需要对candidates进行排序
backtrack(result, new ArrayList<>(), candidates, target, 0);
}
private void backtrack(List> result, List tempList, int[] candidates, int remain, int start) {
if (remain < 0) {
// 如果 remain 小于 0,表示当前的组合不符合要求,直接返回
return;
} else if (remain == 0) {
// 如果 remain 等于 0,表示当前的组合符合要求,加入到结果中
result.add(new ArrayList<>(tempList));
} else {
for (int i = start; i < candidates.length; i++) {
if (i > start && candidates[i] == candidates[i - 1]) {
continue;
// 避免重复计算,如果当前数字和上一个数字相同,则跳过
}
tempList.add(candidates[i]); // 将当前数字加入到临时列表中
backtrack(result, tempList, candidates, remain - candidates[i], i + 1);
// 递归调用,继续向下搜索
tempList.remove(tempList.size() - 1);
// 回溯,将最后加入的数字移除,尝试下一个数字
}
}
}
}
回溯算法是⼀种⾮常重要的算法,可以解决许多组合问题、排列问题和搜索问题等。回溯算法的核⼼ 思想是搜索状态树,通过遍历状态树来实现对所有可能解的搜索。回溯算法的模板⾮常简单,但是实 现起来需要注意⼀些细节,⽐如如何做出选择、如何撤销选择等。
题目链接:77. 组合 - 力扣(LeetCode)
算法原理描述
这个问题的核心是从 1 到 n 中选择 k 个数的所有组合,而不考虑顺序。为了实现这一目标,我们可以采用深度优先搜索(DFS)的方法来生成所有可能的组合。
类定义及变量初始化
类定义:
- 定义一个名为
Solution
的类来封装解决方案逻辑。成员变量初始化:
List
: 用于存储当前的组合路径。path List
: 用于存储所有有效的组合结果。> ret
int max
: 表示总的元素数量 n。int num
: 表示每个组合需要选择的元素数量 k。主方法实现
- 主方法
combine
:
- 初始化
path
和ret
。- 设置
max
和num
。- 从 1 开始调用
dfs
方法开始递归。- 最后返回
ret
,即所有有效的组合。递归方法实现
- 递归方法
dfs
:
- 参数
cur
表示当前正在考虑放置哪个数字。- 递归的基本结束条件是当
path
的大小等于num
时,此时已经找到了一个有效的组合,将其添加到结果集中ret
并返回。- 对于每一个数字
i
(从cur
开始到max
),执行以下操作:
- 将
i
添加到当前组合path
中。- 调用
dfs(i + 1)
进行下一层递归。- 在递归返回后,从
path
中移除最后一个添加的元素i
,这是回溯的过程,以便尝试下一个可能的组合。
代码实现:
class Solution {
//这里的组合就是简单的子排列
List path;
List> ret;
int max,num;
public List> combine(int n, int k) {
path = new ArrayList<>();
ret = new ArrayList<>();
max = n;
num = k;
dfs(1);
return ret;
}
//这里cur指的是当前要放置的数字
public void dfs(int cur){
//出口
if(path.size()==num){
ret.add(new ArrayList<>(path));
return;
}
for(int i = cur;i<=max;i++){
path.add(i);
dfs(i+1);
//回溯
path.remove(path.size()-1);
}
}
}
动动手点个赞会让作者更开心,感谢阅览,加油各位 !