回溯(Backtracking)和剪枝(Pruning)是算法设计中常用的两个概念,它们通常在解决组合优化问题或搜索问题时发挥作用。
-
回溯:
回溯是一种试探性的搜索算法,通常用于在一个问题的解空间中搜索问题的解。这种方法通过不断地尝试找到问题的解,当发现当前的解无法满足问题的约束条件时,就会回退(backtrack)到之前的状态,然后尝试其他的可能性。回溯算法通常以递归的形式实现。
典型的应用包括八皇后问题、数独问题等。在这些问题中,你尝试放置一个皇后或填充一个数,如果当前的尝试导致冲突,就回溯到上一个状态重新尝试。
-
剪枝:
剪枝是在搜索树中去除一些分支,以减少搜索空间的技术。剪枝可以通过一些条件判断,提前舍弃一些不可能产生最优解的分支,从而减少搜索的时间和空间复杂度。
剪枝的目的是避免对不可能产生解的部分进行搜索,从而提高算法的效率。剪枝可以在回溯算法中应用,也可以在其他搜索算法中使用。
总的来说,回溯和剪枝通常一起使用,回溯用于搜索解空间,而剪枝用于优化搜索过程,排除一些明显不可能产生最优解的情况。这两个概念经常在深度优先搜索(DFS)等问题中相互配合,以提高算法的效率。
例题 力扣77
public class CombinationLeetcode77 {
static List<List<Integer>> combine(int n, int k) {
List<List<Integer>> result = new ArrayList<>();
dfs(1, n, k, new LinkedList<>(), result);
return result;
}
// start 起始处理数字
static void dfs(int start, int n, int k, LinkedList<Integer> stack, List<List<Integer>> result) {
if (stack.size() == k) {
result.add(new ArrayList<>(stack));
return;
}
//i=1,2,3,4
for (int i = start; i <= n; i++) {
if(k - stack.size() > n - i + 1){
continue;
}
stack.push(i);// i = 1
dfs(i + 1, n, k, stack, result);
stack.pop();
}
}
public static void main(String[] args) {
List<List<Integer>> lists = combine(4, 3);
/*
n 数字范围1~4
k 数字个数
12
13
14
23
24
34
*/
System.out.println(lists);
for (List<Integer> list : lists) {
System.out.println(list);
}
}
}