刷题日记04《回溯算法》

回溯算法本质

回溯算法的本质是穷举,即对所有可能的情况进行一一穷举,如果求解过程中发现某个情况不符合求解要求,直接进行剪枝即可

回溯算法模板

我们可以将回溯算法理解为以下两种模板

1.递归回溯

result = []
def backtrack(路径, 选择列表):
    if 满足结束条件:
        result.add(路径)
        return
    
    for 选择 in 选择列表:
        做选择
        backtrack(路径, 选择列表)
        撤销选择

2.多叉树的遍历

void traverse(TreeNode root) {
    for (TreeNode child : root.childern) {
        // 前序位置需要的操作
        traverse(child);
        // 后序位置需要的操作
    }
}

题目实例

题目描述

力扣icon-default.png?t=N5K3https://leetcode.cn/problems/permutations/

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

解题思路

对于回溯算法的题目,我们直接修改小部分的算法策略后直接套用回溯模板即可:针对这道题目,我们的实现思路如下:对于每一层数字的排列,我们一一穷举其可能的情况,之后将可能的情况进行保存,不可能的情况直接丢弃,在可能情况的基础上进行下一层的递归遍历,在递归最后一层数字后将代码进行回溯~

代码实现

class Solution {
    //定义结果集
    private LinkedList<List<Integer>> res=new LinkedList<>();
    public List<List<Integer>> permute(int[] nums) {
        //调用递归函数
        //创建列表
        LinkedList<Integer>list=new LinkedList<>();
        reverse(list,nums);
        return res;
    }
    //创建递归函数
    public void reverse(LinkedList<Integer>list,int[]nums){
        //判断递归的终止条件
        if(list.size()==nums.length){
            //导出
            res.addLast(new LinkedList(list));
        }
        //进入递归
        for(int i=0;i<nums.length;++i){
            if(list.contains(nums[i])){
                continue;
            }
            //加入列表
            list.addLast(nums[i]);
            //递归
            reverse(list,nums);
            list.removeLast();
        }
    }
}

题目描述

N皇后问题

解题思路

N皇后问题也是直接套用模板即可:在每一层皇后的选择中遍历所有情况,将不符合条件的情况进行摒弃,继续向下一层进行递归遍历,直到满足所有情况后进行回溯即可

代码实现

public class NEmpress {
    private static final  int N=8;
    public static int process(int[]data,int i,int n){
        //定义计数器
        int res=0;
        if(i==n){
            return 1;
        }
        //进行递归遍历
        for(int j=0;j<n;++j){
            //判断当前列是否有效
            if(isValid(data,i,j)){
                data[i]=j;
            }
            //递归
          res+=process(data, i+1, n);
            //回溯
            data[i]=0;
        }
        return res;
    }

    private static boolean isValid(int[] data, int i, int j) {
        for(int k=0;k<i;++k){
            if(data[k]==j||Math.abs(i-k)==Math.abs(j-data[k])){
                return false;
            }
        }
        return true;
    }
}

猜你喜欢

转载自blog.csdn.net/m0_65431718/article/details/131514832
今日推荐