一个框架解决回溯算法

什么是回溯算法,先上百度百科定义:

回溯算法实际上一个类似枚举的搜索尝试过程,主要是在搜索尝试过程中寻找问题的解,当发现已不满足求解条件时,就“回溯”返回,尝试别的路径。回溯法是一种选优搜索法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。许多复杂的,规模较大的问题都可以使用回溯法,有“通用解题方法”的美称。

总结,如下图,如果我们需要知道下图中从顶点1到顶点5总共有多少条路径,我们会先站在顶点1,会面临着两个选择[2,3],如果选择顶点2,也会有两个选择[4,6],假如我们选择4,只有一个选择直接到顶点5,发现顶点5是我们的终点,所以就会把[1,2,4,5]这条路径加入结果集,顶点5继续走发现没路了,就会回退到上一次选择,顶点4,发现顶点4也没有选择了,会继续回退到顶点2,到顶点2发现还有顶点6没走,就会走顶点6.循环以上步骤,直到没有任何选择了,循环结束。

总之,回溯就是每到一个点,管他三七二十一,选选择一条路径,怼下去,怼不通就回退到上一个继续怼,怼通了就加入结果集,直到所有路都怼完。

在这里插入图片描述

现在我们知道回溯算法是什么了之后,上框架,框架来自微信公众号:labuladong。

result = [] //结果集
def backtrack(路径,选择列表): //定义函数
	if 满足结束条件:
		result.add(路径);  //加入结果集
		return;
	for 选择 in 选择列表:  //循环选择列表
		做选择
		backtract(路径,选择列表)	//递归
		撤销选择

核心就是for循环里面的递归,在递归之前[做选择],在递归之后[撤销选择]。

好了,框架上完了,我们直接上题目

全排列

在这里插入图片描述
在leetcode的难度是中等,他的全排列有 n! 种,我画出了他的图,接下来我们直接套公式
在这里插入图片描述

class Solution {
    /**
    * 结果集
    **/
    List<List<Integer>> res = new LinkedList<>();
    public List<List<Integer>> permute(int[] nums) {
        backtrack(nums, new LinkedList<Integer>());
        return res;
    }
    /**
    * nums选择列表
    * track 路径
    **/
    public void backtrack(int[] nums, LinkedList<Integer> track){
        //触发结束条件
        if(track.size() == nums.length){
            /**
            *加入结果集,用new LinkedList的原因是因为track指向的是一块内存,
            *如果不新创建一块内存空间放现在的结果,后续操作会更改内存里面的值,
            *最终导致所有结果一样
            **/
            res.add(new LinkedList(track)); 
            return;
        }
        for(int num : nums){
            //撤销不合法的选择
            if(track.contains(num)) continue;
            //做选择
            track.add(num);
            //递归,进入下一次决策
            backtrack(nums, track);
            //撤销选择
            track.removeLast();
        }
    }
}
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值