回溯、剪枝

269 阅读2分钟

回溯(Backtracking)和剪枝(Pruning)是算法设计中常用的两个概念,它们通常在解决组合优化问题或搜索问题时发挥作用。

  1. 回溯:

    回溯是一种试探性的搜索算法,通常用于在一个问题的解空间中搜索问题的解。这种方法通过不断地尝试找到问题的解,当发现当前的解无法满足问题的约束条件时,就会回退(backtrack)到之前的状态,然后尝试其他的可能性。回溯算法通常以递归的形式实现。

    典型的应用包括八皇后问题、数独问题等。在这些问题中,你尝试放置一个皇后或填充一个数,如果当前的尝试导致冲突,就回溯到上一个状态重新尝试。

  2. 剪枝:

    剪枝是在搜索树中去除一些分支,以减少搜索空间的技术。剪枝可以通过一些条件判断,提前舍弃一些不可能产生最优解的分支,从而减少搜索的时间和空间复杂度。

    剪枝的目的是避免对不可能产生解的部分进行搜索,从而提高算法的效率。剪枝可以在回溯算法中应用,也可以在其他搜索算法中使用。

总的来说,回溯和剪枝通常一起使用,回溯用于搜索解空间,而剪枝用于优化搜索过程,排除一些明显不可能产生最优解的情况。这两个概念经常在深度优先搜索(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);
        }


    }


}