算法学习笔记(一)——全排列问题之回溯法


今天看了好久的全排列问题!虽然说,之前通过全排列的生成问题算法(上次写的博客里详细讲解了该算法)很完美的解决了这个问题!但是近两天为了更好地理解回溯法!因而看了一下午的回溯解法,我终于看懂了(《算法学习笔记(一)——全排列问题之回溯法》真特么不容易)!
为了更好地说明,我以12345的全排列为例!首先将其放在一个数组中(从小到大),开始循环,如果1234已被选中,那么久需要将1234标记为已选,那么候选元素只剩下5,那么一种全排列也就出来了。显然到这里,需要回溯!那么问题来了,怎么回溯呢?看了之后别人博客上写的算法:意思是这样的!当执行到这里的时候,就将5标记为未选中(此次已成功搜索到一个排列),这时这层循环(第6层)也就结束了。那么自然也就回溯到上一层(第五层),到了第五层,同理4也选完了,自然也标记为未选中了。由于5这个位置空出来了,那么第五层就可以选五,而到了第六层,4被空出来了;那么第六层就自然选4咯!如此回溯,探索!可以得到最终所有解!
         好了,思路说完了。接下来直接上代码:

public class Demo4 { int size; int[] vector;//存储当前解向量 boolean[] used;//存储当前解空间中哪些数据已经被使用过 int amount = 0; public Demo4(int size){ this.size = size; vector = new int[size]; used = new boolean[size]; } /** * 迭代算法,通过used数组来确定当前层可用解,然后进入下一层重复通用动作。 * 当到最终层后修改used数组,回溯。 * @param level 当前层,对应为解向量的数组下标。 */ public void sort(int level){ for(int i=0;i<size;i++){//从0到size-1,一共size层 if(!used[i]){//找到当前层第一个没有被使用的解 vector[level]=i;//把这个解赋予解向量的当前层 used[i] = true;//标记当前解已经被使用 if(level!=size-1)//如果不是最后一层,则递归进行下一层的排序 sort(level+1); else System.out.println((++amount)+”:”+Arrays.toString(vector));//如果是最后一层,打印输出 used[i]=false;//这是回溯的关键! /* * 到达上一条语句的来源,可以分为两种情况: * 1是到达最后一层,i是最后一个可用元素在解空间的下标,自然要将其对应的解“解锁”,即标为未使用。 * 2是刚刚推出递归,也就是当前层的解为解空间i的情况刚刚递归完成,所以也要对解进行“解锁”。 */ } } } public static void main(String[] args) { new Demo4(6).sort(0); } }


代码上面的注释也写得蛮清楚的,相信各位看官也都看得懂!回溯的关键点之一就是找好回溯点,觉得这个算法真的满巧妙的!通过设置全局变量实现的数字的动态变化!真心的要点个赞!

    原文作者:回溯法
    原文地址: https://blog.csdn.net/renshengkudaun/article/details/51048938
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞