美文网首页
回溯算法

回溯算法

作者: Raral | 来源:发表于2022-03-03 19:50 被阅读0次

    回溯算法

    概述

    废话不多说,直接上回溯算法框架。解决⼀个回溯问题,实际上就是⼀个决 策树的遍历过程。你只需要思考 3 个问题:

    1、路径:也就是已经做出的选择。

    2、选择列表:也就是你当前可以做的选择。

    3、结束条件:也就是到达决策树底层,⽆法再做选择的条件。

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

    其核⼼就是 for 循环⾥⾯的递归,在递归调⽤之前「做选择」,在递归调⽤ 之后「撤销选择」,特别简单。

    什么叫做选择和撤销选择呢,这个框架的底层原理是什么呢?下⾯我们就通 过「全排列」这个问题来解开之前的疑惑,详细探究⼀下其中的奥妙!

    注意: 回溯算法的核心操作,就是 撤销选择

    全排列问题

    我们在⾼中的时候就做过排列组合的数学题,我们也知道 n 个不重复的 数,全排列共有 n! 个。

    [图片上传失败...(image-32d13-1646308220929)]

    PS:为了简单清晰起⻅,我们这次讨论的全排列问题不包含重复的数字。

    转换成代码语言 =》 //计算 [1,2,3] 全排列 多少种?并且把所有的排练情况 输出

    public class Test {
        // 存储 所有排列的情况,存放到list
        public static List<List<Integer>> res = new LinkedList<>();
    
        public static void main(String[] args) {
                //计算 [1,2,3] 全排列 多少种?并且把所有的排练情况 输出
           int[] nums = {2,3};
            List<List<Integer>> premute = premute(nums);
            System.out.println(premute);
    
        }
    
        public static List<List<Integer>> premute(int[] nums) {
            //记录【路径】
            LinkedList<Integer> track = new LinkedList<>();
            //回溯
            backtrack(nums, track);
            return res;
        }
        // 路径:记录在 track 中
        // 选择列表:nums 中不存在于 track 的那些元素
        // 结束条件:nums 中的元素全都在 track 中出现
        public static void backtrack(int[] nums, LinkedList<Integer> track) {
            //【触发结束条件】;
            if(track.size() == nums.length) {
                res.add(new LinkedList<>(track));//将一种排列,存放到链表前面
            }
            //【遍历路径选择】
            for(int i = 0; i < nums.length; i ++) {
                //【排除不合法的】
                if(track.contains(nums[i])) continue;
                //【做选择】,剩下选择一个
                track.add(nums[i]);
                //【递归】
                backtrack(nums, track);
                //【取消选择】就是回溯核心 : 以一个完整的排列,把完整队列,最后一个位置后退,重新选择
                // 相当于 回退到选择最后一条路
                track.removeLast();
            }
    
        }
    

    [图片上传失败...(image-e89e60-1646308220929)]

    N 皇后问题

    这个问题很经典了,简单解释⼀下:给你⼀个 N×N 的棋盘,让你放置 N 个 皇后,使得它们不能互相攻击。 PS:皇后可以攻击同⼀⾏、同⼀列、左上左下右上右下四个⽅向的任意单 位。

    相关文章

      网友评论

          本文标题:回溯算法

          本文链接:https://www.haomeiwen.com/subject/gsuurrtx.html