回溯算法初识入门

703 阅读2分钟

这是我参与更文挑战的第26天,活动详情查看: 更文挑战

回溯算法

回溯算法是一种纯暴力递归搜索算法,也可以说成是深度优先搜索算法。

回溯法采用试错的思想,它尝试分步的去解决一个问题。在分步解决问题的过程中,当它通过尝试发现,现有的分步答案不能得到有效的正确的解答的时候,它将取消上一步甚至是上几步的计算,再通过其它的可能的分步解答再次尝试寻找问题的答案。回溯法通常用最简单的递归方法来实现,在反复重复上述的步骤后可能出现两种情况:

  • 找到一个可能存在的正确的答案
  • 在尝试了所有可能的分步方法后宣告该问题没有答案

框架模板

回溯算法的实现过程就是一颗多叉树的遍历搜索过程。其中涉及到的状态我们可以归纳为:

  • List<List> res:存储最终返回的结果
  • int depth:当前遍历的层数
  • int[] nums:给定的已知数组
  • boolean[] used:标识当前结点是否被访问过
  • Qeque path:存储从根结点到目前结点之间的路径结点
List<List<Integer>> res;
void backTracking(路径,选择列表){
     if(满足约束条件){
        res.add(路径);
        return;
     }

     for(选择:选择列表){
         做选择;
         backTracking(路径:选择列表);
         撤销选择;
     }
}

实例演示

给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。

输入:nums = [1,2,3]

输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]

class Solution {
    public List<List<Integer>> permute(int[] nums) {
        List<List<Integer>> res=new ArrayList<>();
        Deque<Integer> path=new ArrayDeque<Integer>();
        boolean[] used=new boolean[nums.length];
        backTracking(nums,0,res,path,used);
        return res;
    }

    public void backTracking(int[] nums,int depth, List<List<Integer>> res, Deque<Integer> path,boolean[] used){
        if(nums.length==depth){
            res.add(new ArrayList<>(path));
            return;
        }

        for(int i=0;i<nums.length;i++){
            if(!used[i]){
                path.push(nums[i]);
                used[i]=true;
                backTracking(nums,depth+1,res,path,used);
                used[i]=false;
                path.removeFirst();
            }
        }
    }
}

原题链接:leetcode-cn.com/problems/pe…