全排列的概念
全排列是什么?
全排列的本质
讲人话:从一个数组中抽取确定量数量的元素,组成一个新的数组。并根据题中的问题,对新组成的数组进行条件
判断。是否满足条件,如果满足条件,就做出一定的代码行为。
伪代码如下
全排列函数体(){
数组 [] list =现有确定;
if(满足条件( list )){
执行目标函数;
return ; 这里必须要加,不加是给自己debug添堵
}
}
满足条件(数组[] list){
条件判断函数;
}
以上是对某一单一排列做出的条件判断,而我们的目标是对一个数组,[] list,做出条件判断。那么问题就来了,如果枚举出所有的情况呢?
生成一个数组的所有排列
您看到这篇文章的时候应该已经做过一些题了,可能会感觉到非常困惑,为啥咱就是看不懂他们写的代码?
例如有些大佬,交换一下数组中的元素就形成了排列。有些大佬对元素位置判断一下就形成了排列。
原理讲解
从一个数组中取出N个元素,形成一个新的数组。我们实际是按照N位元素,在N的每一位上,不重复的添加元素,并继
续向下一位添加。(这里描述有点问题,自己动脑子想一想,兄弟语文不好)
举例说明:从[1,2,3]中,抽取两个2元素,组成全排列。当第一位取1的时候,后面的第二位便无法取1,只能取2或
3
看到这里,你肯定已经明白了全排列用代码实现的原理(每一位,在当前位可取的范围进行枚举,然后转移到下一位)
如果当前位枚举了一个元素,则后面位不可使用。
伪代码:
[] 当前可选取的情况;
for(int i :当前可选取的情况){
当前位置 =i;0
//因为当前位置选取了i,所以要把i从当前可选取的情况中去除掉,以免后面的元素选取
当前可选取的情况 扣除i;
进行下一层的枚举(K+1); //确定了第K位,我们现在需要枚举第K+1位
//当前 层 的所有子情况已经讨论完毕,既 ABC ----的情况已经讨论完毕,排列将进入ABD----的情况
//i不会在这一层被选取了,所以要恢复i
当前可选取的情况增加i;
}
另一种方式
从当前层开始for循环,交换数组元素。 原理是利用这样子交换当前层通样不会重复,自己去想。
这个其实和上面的方法大同小异,只是代码写起来少个两三排。因为这个方法没有保证全排列的有序性(出现顺序),
自己想一下[1,2,3]的全排列使用这个方法是什么样子的。
模板
递归出口什么的多自己想想,懒得写了,网课杀我
import java.util.*;
public class 蓝桥排列 {
static char[] list = "LANQIAO".toCharArray();
static boolean[] vis = new boolean[7];//判断在当前状况下,哪一位已经被取了
static char[] put = new char[7]; //存放每一位的情况
public static HashSet<String> set = new HashSet<String>();//用于最终的条件判断
public static void main(String[] args) {
dfs(0);
for(String i:set) {System.out.println(i);}
System.out.println(set.size());
}
//不知道dfs是什么的朋友自己百度,这个简单
public static void dfs(int pos) {
if(pos==7) {//已经枚举了所有位(7位),进行条件判断。并中止
set.add(new String(put));
return ;
}
for(int i=0;i<vis.length;i++) {
if(!vis[i]) {
vis[i]=true;
put[pos]=list[i];
dfs(pos+1);
vis[i]=false;
}
}
}
}