Java 全排列与组合
Posted ZSYL
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java 全排列与组合相关的知识,希望对你有一定的参考价值。
排列组合是组合学最基本的概念。
所谓排列,就是指从给定个数的元素中取出指定个数的元素进行排序。
组合则是指从给定个数的元素中仅仅取出指定个数的元素,不考虑排序。
----- 百度百科
全排列
概念
一般地说,从n个不同元素中,任取m(m≤n)个元素,按照一定的顺序排成一列,这就叫做从n个元素中取出m个元素的一个排列。
公式:
当 m=n 时,便称为全排列
此外规定0! = 1
因此:全排列公式:n!
分析
举例:
1,2,3的全排列有:
1,2,3
1,3,2
2,1,3
2,3,1
3,1,2
3,2,1
考虑建立二叉树
对于每一种排列的,都需要选择 首元素,之后第一个元素与剩下的元素依次类推,每一步都选择一个元素,直到全部元素选择完毕。
考虑使用递归,底层是栈,每一次出栈,后我们还原上一次的现场,重现修改之前选择的元素,再次进栈。
代码展示
import java.util.Arrays;
public class Main {
static int[] a;
public static void main(String[] args) {
a = new int[]{1, 2, 3, 4};
fullSort(0, a.length-1);
}
public static void fullSort(int s, int e) {
// 递归结束条件
if (s == e) {
System.out.println(Arrays.toString(a));
}
// 脑海中形成二叉树的形状,对于当前需要选择一个元素做首,之后从该元素向下递归
// 对于 s-e 所有元素都可放在首,因此 for循环,每次递归后,回溯需要还原现场
for (int i = s; i <= e; i++) {
// 交换首元素
swap(s, i);
fullSort(s+1, e);
// 交换元素复原,不影响下一次的选择
swap(s, i);
}
}
// 交换元素函数
public static void swap(int i, int j) {
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
结果:
组合
概念
组合的定义:
从n个不同元素中,任取m(m≤n)个元素并成一组,叫做从n个不同元素中取出m个元素的一个组合;
从n个不同元素中取出m(m≤n)个元素的所有组合的个数,叫做从n个不同元素中取出m个元素的组合数。
用符号 C(n,m) 表示。
公式:
或者是:
n * (n-1)…(n-m+1) / m!
枚举1-n所有组合,随机选取任意多个
分析
例如:
n=2,有3种情况:
1
2
12
对于1-n 的每一个数,我们有选择与不选择两种情况,对于每次选择之后,求解子问题,一直到结束条件,考虑使用递归,注意每次选择后,需要还原现场。
代码展示
import java.util.Scanner;
import java.util.Vector;
// 枚举1-n所有组合,随机选取任意多个
public class _01_enumerateAll {
static int n;
static Vector<Integer> vector = new Vector<>();
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
calc(1);
}
public static void calc(int x) {
// 递归结束条件,遍历到最后
if (x == n+1) {
for (int i : vector) {
System.out.print(i + " ");
}
System.out.println();
return;
}
// 不选x分支
calc(x+1);
// 选择x
vector.add(x);
// 求解子问题
calc(x+1);
// 回溯上一个问题之前,还原现场
vector.remove((Object)x);
}
}
枚举1-n所有组合,随机选取m个数
与上面类似,只需修改递归结束条件即可
代码展示
import java.util.Scanner;
import java.util.Vector;
// 枚举1-n所有组合,随机选取m个数
public class _02_enumerateN {
static int n, m;
static Vector<Integer> vector = new Vector<>();
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
m = sc.nextInt();
calc(1);
}
public static void calc(int x) {
// 剪枝操作,减去不必要的递归,提前出栈
// 当选择的数 > m 时,或者 剩下的数,不够选时,return;
if (vector.size() > m || vector.size() + (n-x+1) < m)
return;
if (vector.size() == m) {
for (int i : vector) {
System.out.print(i + " ");
}
System.out.println();
return;
}
// 不选x分支
calc(x+1);
// 选择x
vector.add(x);
// 求解子问题
calc(x+1);
// 回溯上一个问题之前,还原现场
vector.remove((Object)x);
}
}
感谢
努力
加油
以上是关于Java 全排列与组合的主要内容,如果未能解决你的问题,请参考以下文章