排列组合介绍
排列,就是指从给定n个数的元素中取出指定m个数的元素,进行排序。
组合,则是指从给定n个数的元素中仅仅取出指定m个数的元素,不考虑排序。
全排列(permutation)
以数字为例,全排列就是从“第一个数字”起,“每个数字”分别与它“后面的数字”交换,复杂度为O(n!)
图示:
A依次和BC交换
交换一次后不急(如AB交换后,不急着交换AC),target后移,再依次交换
直到target=最后一个数时,停止,输出
返回上一步(很明显,用递归)接着做,此时注意,要把换了的数再还回来
代码:数组实现全排列
package hulaoshi.permutation;
public class Common {
static void swap(char str[], int a, int b) {
if (a == b) {
return;
}
char temp = str[a];
str[a] = str[b];
str[b] = temp;
}
static void printArr(char str[]) {
for (char c : str) {
System.out.print(c + " ");
}
System.out.println();
}
}
package hulaoshi.permutation;
public class 全排列 {
static int count = 0;
static void permutation(char str[], int t) {
if (t == str.length - 1) {
// 3.停止
System.out.print(++count + ": ");
Common.printArr(str);
return;
}
for (int i = t; i < str.length; i++) {
Common.swap(str, t, i);
// 2.递归
permutation(str, t + 1);
// 4.返回上层,换回来
Common.swap(str, t, i);
}
}
public static void main(String[] args) {
char str[] = new String("ABC").toCharArray();
// 1.从0开始
permutation(str, 0);
}
}
结果:
1: A B C
2: A C B
3: B A C
4: B C A
5: C B A
6: C A B
组合:数组实现
package hulaoshi.permutation;
public class 组合 {
static char[] _original = "ABCDE".toCharArray();
static int N = _original.length;
static int M = 3;
static int[] _indexArr = new int[M];
static void C(int n, int m) {
// 1.以5取3为例,n=5,m=3,遍历下标【2~4】,取第3个元素【m-1】
for (int i = m - 1; i <= n - 1; i++) {
// 2.下标存入
_indexArr[m - 1] = i;
if (m == 1) {
printArr();
// 4.不要return,循环还要继续
continue;
}
// 3.剩下的递归,剩下i个元素,取m-1个
C(i, m - 1);
}
}
static void printArr() {
for (int i : _indexArr) {
System.out.print(_original[i]);
}
System.out.println();
}
public static void main(String[] args) {
C(N, M);
}
}
结果:
ABC
ABD
ACD
BCD
ABE
ACE
BCE
ADE
BDE
CDE
排列:列表实现
就是一个数字一个数字地扫,为避免递归时,已经确定的数还回(如数组实现全排列时的两个swap,每次递归时创建一个新的ArrayList)
package hulaoshi.permutation;
import java.util.ArrayList;
public class 排列组合2 {
static char[] _原序列 = "ABC".toCharArray();
static int total;
static int n = _原序列.length;
static int m = 2;
static void printArray(ArrayList lstIdx) {
for (Integer i : lstIdx) {
System.out.print(_原序列[i]);
}
System.out.println();
}
static void A(int m, ArrayList lstIdx) {
if (m == 0) {
// 递归完毕,打印出来
printArray(lstIdx);
total++;
return;
}
for (int i = 0; i < n; i++) {
// 上一次调用本方法时的ArrayList,不改
// 创建新的ArrayList,为的是递归完毕时,旧的ArrayList不变
ArrayList lstIdx2 = new ArrayList();
lstIdx2.addAll(lstIdx);
if (!lstIdx.contains(i)) {
lstIdx2.add(i);
// 递归调用,将ArrayList传进去,但函数内会生成新的,把这个完全包含
A(m - 1, lstIdx2);
}
}
}
public static void main(String[] args) {
A(m, new ArrayList());
System.out.println("total : " + total);
}
}
结果:
AB
AC
BA
BC
CA
CB
total : 6