排列
场景一 (拿球可放回)
-
假设袋子里有编号为1,2,…,m这m个球。现在每次从袋子中取一个球记下编号,放回袋中再取,取n次作为一组,枚举所有可能的情况。
-
分析: 每一次取都有m种可能的情况,因此一共有种情况。
-
这里我们取m = 3, n = 4,则有 3 4 3^{4} 34 种不同的情况。
以下代码非常巧妙(通俗易懂)
package BaseFunction;
import java.util.Stack;
public class PermutationAndcombination {
static int cnt = 0;
static Stack<Integer> s = new Stack<Integer>();
/**
* 递归方法,当实际选取的小球数目与要求选取的小球数目相同时,跳出递归
* @param minv - 小球编号的最小值
* @param maxv - 小球编号的最大值
* @param curnum - 当前已经确定的小球的个数 --> 有点类似于 count 计数器的意思
* @param maxnum - 要选取的小球的数目
* 3 ^ 4
*/
public static void kase1(int minv,int maxv,int curnum, int maxnum){
if(curnum == maxnum){
cnt++;
System.out.println(s);
return;
}
for(int i = minv; i <= maxv; i++){
s.push(i);
kase1(minv, maxv, curnum+1, maxnum);
s.pop(); //回溯
}
}
public static void main(String[] args){
kase1(1, 3, 0, 4);
System.out.println(cnt);
}
}
输出:
[1, 1, 1, 1]
[1, 1, 1, 2]
[1, 1, 1, 3]
[1, 1, 2, 1]
[1, 1, 2, 2]
[1, 1, 2, 3]
[1, 1, 3, 1]
[1, 1, 3, 2]
[1, 1, 3, 3]
[1, 2, 1, 1]
[1, 2, 1, 2]
[1, 2, 1, 3]
[1, 2, 2, 1]
[1, 2, 2, 2]
[1, 2, 2, 3]
[1, 2, 3, 1]
[1, 2, 3, 2]
[1, 2, 3, 3]
[1, 3, 1, 1]
[1, 3, 1, 2]
[1, 3, 1, 3]
[1, 3, 2, 1]
[1, 3, 2, 2]
[1, 3, 2, 3]
[1, 3, 3, 1]
[1, 3, 3, 2]
[1, 3, 3, 3]
[2, 1, 1, 1]
[2, 1, 1, 2]
[2, 1, 1, 3]
[2, 1, 2, 1]
[2, 1, 2, 2]
[2, 1, 2, 3]
[2, 1, 3, 1]
[2, 1, 3, 2]
[2, 1, 3, 3]
[2, 2, 1, 1]
[2, 2, 1, 2]
[2, 2, 1, 3]
[2, 2, 2, 1]
[2, 2, 2, 2]
[2, 2, 2, 3]
[2, 2, 3, 1]
[2, 2, 3, 2]
[2, 2, 3, 3]
[2, 3, 1, 1]
[2, 3, 1, 2]
[2, 3, 1, 3]
[2, 3, 2, 1]
[2, 3, 2, 2]
[2, 3, 2, 3]
[2, 3, 3, 1]
[2, 3, 3, 2]
[2, 3, 3, 3]
[3, 1, 1, 1]
[3, 1, 1, 2]
[3, 1, 1, 3]
[3, 1, 2, 1]
[3, 1, 2, 2]
[3, 1, 2, 3]
[3, 1, 3, 1]
[3, 1, 3, 2]
[3, 1, 3, 3]
[3, 2, 1, 1]
[3, 2, 1, 2]
[3, 2, 1, 3]
[3, 2, 2, 1]
[3, 2, 2, 2]
[3, 2, 2, 3]
[3, 2, 3, 1]
[3, 2, 3, 2]
[3, 2, 3, 3]
[3, 3, 1, 1]
[3, 3, 1, 2]
[3, 3, 1, 3]
[3, 3, 2, 1]
[3, 3, 2, 2]
[3, 3, 2, 3]
[3, 3, 3, 1]
[3, 3, 3, 2]
[3, 3, 3, 3]
81
场景二(拿球不可放回)排列
纯代码实现 A ( n m ) n\choose m (mn)
package BaseFunction;
/**
* @author LZH.create
* 排列 程序实现
*/
public class arrangement {
public static void main(String[] args) {
// 计算 A(3 , 6)
System.out.println(A(3,6));
}
// A(n , m)
public static int A(int m ,int n) {
int result = 1 ;
// m 控制循环次数
for(int i = m ; i > 0 ;i--) {
result *= n ;
n-- ;
}
return result ;
}
}
-
假设袋子里有编号为1,2,…,m这m个球。先后从袋子中取出n个球,依次记录编号,枚举所有可能的情况。
-
分析:这是排列问题,应该有A ( n m ) n\choose m (mn)种情况
这里取m = 5, n = 3,A ( 3 5 ) 3\choose 5 (53)。
和问题1相比,唯一的区别是排列中不可以有重复。因此开了used数组用以标记是否已经访问。
import java.util.Stack;
public class Test {
static int cnt = 0;
static Stack<Integer> s = new Stack<Integer>();
static boolean[] used = new boolean[10000];
/**
* 递归方法,当实际选取的小球数目与要求选取的小球数目相同时,跳出递归
* @param minv - 小球编号的最小值
* @param maxv - 小球编号的最大值
* @param curnum - 当前已经确定的小球的个数
* @param maxnum - 要选取的小球的数目
*/
public static void kase2(int minv,int maxv,int curnum, int maxnum){
if(curnum == maxnum){
cnt++;
System.out.println(s);
return;
}
for(int i = minv; i <= maxv; i++){
if(!used[i]){
s.push(i);
used[i] = true;
kase2(minv, maxv, curnum+1, maxnum);
s.pop();
used[i] = false;
}
}
}
public static void main(String[] args){
kase2(1, 5, 0, 3);
System.out.println(cnt);
}
}
输出:
[1, 2, 3]
[1, 2, 4]
[1, 2, 5]
[1, 3, 2]
[1, 3, 4]
[1, 3, 5]
[1, 4, 2]
[1, 4, 3]
[1, 4, 5]
[1, 5, 2]
[1, 5, 3]
[1, 5, 4]
[2, 1, 3]
[2, 1, 4]
[2, 1, 5]
[2, 3, 1]
[2, 3, 4]
[2, 3, 5]
[2, 4, 1]
[2, 4, 3]
[2, 4, 5]
[2, 5, 1]
[2, 5, 3]
[2, 5, 4]
[3, 1, 2]
[3, 1, 4]
[3, 1, 5]
[3, 2, 1]
[3, 2, 4]
[3, 2, 5]
[3, 4, 1]
[3, 4, 2]
[3, 4, 5]
[3, 5, 1]
[3, 5, 2]
[3, 5, 4]
[4, 1, 2]
[4, 1, 3]
[4, 1, 5]
[4, 2, 1]
[4, 2, 3]
[4, 2, 5]
[4, 3, 1]
[4, 3, 2]
[4, 3, 5]
[4, 5, 1]
[4, 5, 2]
[4, 5, 3]
[5, 1, 2]
[5, 1, 3]
[5, 1, 4]
[5, 2, 1]
[5, 2, 3]
[5, 2, 4]
[5, 3, 1]
[5, 3, 2]
[5, 3, 4]
[5, 4, 1]
[5, 4, 2]
[5, 4, 3]
60
场景三 (一次性取球) 组合
纯代码实现 C ( n m ) n\choose m (mn)
package BaseFunction;
/**
* @author LZH.create
* 组合运算 充分运用 与排列的关系
* C(n,m) = A(n,m) / m! ---> C(n,m) = A(n,m) / A(m,m).
*/
public class combination {
public static void main(String[] args) {
System.out.println(C(2,8));
}
// A(n , m)
public static int A(int m ,int n) {
int result = 1 ;
// m 控制循环次数
for(int i = m ; i > 0 ;i--) {
result *= n ;
n-- ;
}
return result ;
}
public static int C(int m ,int n) {
int son = A(m,n) ;
int mother = A(m,m) ;
return son/mother ;
}
}
-
从m个球里(编号为1,2,3…,m)一次取n个球,其中
m>n
,记录取出球的编号,枚举所有的可能性。 -
分析:这是组合问题。因该有C ( n m ) n\choose m (mn)种可能性。
-
这里,我们取m = 8, n = 4. 因此有C ( 4 8 ) 4\choose 8 (84)种可能。
import java.util.Stack;
public class Test {
static int cnt = 0;
static Stack<Integer> s = new Stack<Integer>();
/**
* 递归方法,当前已抽取的小球个数与要求抽取小球个数相同时,退出递归
* @param curnum - 当前已经抓取的小球数目
* @param curmaxv - 当前已经抓取小球中最大的编号
* @param maxnum - 需要抓取小球的数目
* @param maxv - 待抓取小球中最大的编号
*/
public static void kase3(int curnum, int curmaxv, int maxnum, int maxv){
if(curnum == maxnum){
cnt++;
System.out.println(s);
return;
}
for(int i = curmaxv + 1; i <= maxv; i++){ // i <= maxv - maxnum + curnum + 1
s.push(i);
kase3(curnum + 1, i, maxnum, maxv);
s.pop();
}
}
public static void main(String[] args){
kase3(0, 0, 4, 8);
System.out.println(cnt);
}
}
输出结果:
[1, 2, 3, 4]
[1, 2, 3, 5]
[1, 2, 3, 6]
[1, 2, 3, 7]
[1, 2, 3, 8]
[1, 2, 4, 5]
[1, 2, 4, 6]
[1, 2, 4, 7]
[1, 2, 4, 8]
[1, 2, 5, 6]
[1, 2, 5, 7]
[1, 2, 5, 8]
[1, 2, 6, 7]
[1, 2, 6, 8]
[1, 2, 7, 8]
[1, 3, 4, 5]
[1, 3, 4, 6]
[1, 3, 4, 7]
[1, 3, 4, 8]
[1, 3, 5, 6]
[1, 3, 5, 7]
[1, 3, 5, 8]
[1, 3, 6, 7]
[1, 3, 6, 8]
[1, 3, 7, 8]
[1, 4, 5, 6]
[1, 4, 5, 7]
[1, 4, 5, 8]
[1, 4, 6, 7]
[1, 4, 6, 8]
[1, 4, 7, 8]
[1, 5, 6, 7]
[1, 5, 6, 8]
[1, 5, 7, 8]
[1, 6, 7, 8]
[2, 3, 4, 5]
[2, 3, 4, 6]
[2, 3, 4, 7]
[2, 3, 4, 8]
[2, 3, 5, 6]
[2, 3, 5, 7]
[2, 3, 5, 8]
[2, 3, 6, 7]
[2, 3, 6, 8]
[2, 3, 7, 8]
[2, 4, 5, 6]
[2, 4, 5, 7]
[2, 4, 5, 8]
[2, 4, 6, 7]
[2, 4, 6, 8]
[2, 4, 7, 8]
[2, 5, 6, 7]
[2, 5, 6, 8]
[2, 5, 7, 8]
[2, 6, 7, 8]
[3, 4, 5, 6]
[3, 4, 5, 7]
[3, 4, 5, 8]
[3, 4, 6, 7]
[3, 4, 6, 8]
[3, 4, 7, 8]
[3, 5, 6, 7]
[3, 5, 6, 8]
[3, 5, 7, 8]
[3, 6, 7, 8]
[4, 5, 6, 7]
[4, 5, 6, 8]
[4, 5, 7, 8]
[4, 6, 7, 8]
[5, 6, 7, 8]
70
全排列题目—20蓝桥杯模拟赛
- 将
LANQIAO
中的字母重新排列,可以得到不同的单词, - 如
LANQIAO
、AAILNOQ
等,注意这7个字母都要被用上,单词不一定有具体的英文意义。 - 请问,总共能排列出多少个不同的单词。
解法一
- 数学方法
有两个相同元素的全排列
种数问题。7的阶乘除以2的阶乘,因为有2个字母相同。如果是三个字母相同的话就要除以3的阶乘。
A ( 7 7 ) 7\choose 7 (77) / A ( 2 2 ) 2\choose 2 (22)
解法二
又是难懂的代码 😢
package 省模拟赛;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
public class 字母重新排列 {
public static int count = 0;
public static ArrayList<Integer> list = new ArrayList<Integer>();
public static Set<String> set = new HashSet<String>();
static String[] strs={"L","A","N","Q","I","A","O"};
public static void main(String[] args) {
f();
System.out.println(set.size());
}
public static void f() {
if (list.size() >= 7) {
StringBuilder s=new StringBuilder("");;
for (int i = 0; i <=6; i++) {
s.append(strs[list.get(i)-1]);
}
set.add(s.toString());
return;
}
for (int i = 1; i <=7 ; i++) {
if (!list.contains(i)) { // 判断是否存在
list.add(i);
f();
list.remove(list.size() - 1);
}
}
}
}