这段话是网上抄来:
1、首先看最后两个数4, 5。 它们的全排列为4 5和5 4, 即以4开头的5的全排列和以5开头的4的全排列。
由于一个数的全排列就是其本身,从而得到以上结果。
2、再看后三个数3, 4, 5。它们的全排列为3 4 5、3 5 4、 4 3 5、 4 5 3、 5 3 4、 5 4 3 六组数。
即以3开头的和4,5的全排列的组合、以4开头的和3,5的全排列的组合和以5开头的和3,4的全排列的组合.
从而可以推断,设一组数p = {r1, r2, r3, ... ,rn}, 全排列为perm(p),pn = p - {rn}。
因此perm(p) = r1perm(p1), r2perm(p2), r3perm(p3), ... , rnperm(pn)。当n = 1时perm(p} = r1。
为了更容易理解,将整组数中的所有的数分别与第一个数交换,这样就总是在处理后n-1个数的全排列
举2个例子来说明
123的全排列
--首先遍历元素,然后把遍历到的每一个元素都和第一个元素交换
第一个和第一个交换 就是1和1交换 最后还是123
那么就形成了 123 213 321 这样的3组
(交换后 再换回来 还原成123 因为后面的交换都是在123的基础上交换的 所以swap要写2次)
--检查每一组除了第一个之外的剩余元素, 如果这些元素个数是2,
那么就对这剩下的2个元素全排列 就是123 132 , 213 231 , 321 312
2个元素的全排列很简单 就是把这2个元素交换位置就OK)
1234的全排列
--首先遍历元素,然后把遍历到的每一个元素都和第一个元素交换
那么就形成了 1234 2134 3214 4231 这样的4组
--检查每一组除了第一个之外的剩余元素, 如1234剩余的是234,发现是3个元素
那么问题就转换为求234的全排列了
接下来也是一样 问题转换为求134, 214, 231的全排列
像这样 总是对除了第一个之外的元素全排列, 每次元素的个数都在减少一个,
求N个元素全排列最终就变成求2的元素的全排列了
这里是思维过程 最后才是成品=====================================
package arrange;
public class MyArrange2 {
char arr[];
public MyArrange2(char[] arr) {
this.arr = arr;
}
void function(char[] arr) {
if(arr.length==2){
System.out.println(arr[0]+""+arr[1]);
System.out.println(arr[1]+""+arr[0]);
}else{
for (int i = 0; i < arr.length; i++) {
swap(0, i);
function(getRemain(arr)); //getRemain的作用是取出除了第一个之外的剩余元素
swap(0, i);
}
}
}
char[] getRemain(char[] arr) {
char[] c = new char[arr.length - 1];
for (int i = 0; i < c.length; i++) {
c[i] = arr[i + 1];
}
return c;
}
private void swap(int i, int j) {
char c;
c = arr[i];
arr[i] = arr[j];
arr[j] = c;
}
public static void main(String[] args) {
char[] arr = new char[] { '1', '2', '3' };
MyArrange2 a = new MyArrange2(arr);
a.function(arr);
}
}
这样的程序运行起来后,发现一个问题
那就是输出的总是把问题最小化的结果, 前面已经确定下来的排列都弄丢了
因此下面就有改进的方案
上面是每次递归时 都是新的数组, 每次数组中的元素都在减少
下面是每次递归时 仍是原来的数组,只是每次只处理部分元素,所要处理的元素个数越来越少
==========================================
package arrange;
public class MyArrange3 {
char arr[];
public MyArrange3(char[] arr) {
this.arr = arr;
}
void function(char[] arr,int k) {
if(k==(arr.length-2)){
printHead(arr);
System.out.println(arr[arr.length-2]+""+arr[arr.length-1]);
printHead(arr);
System.out.println(arr[arr.length-1]+""+arr[arr.length-2]);
}else{
for (int i = k; i < arr.length; i++) {
swap(k, i); //这里就不能写0了, 因为本次的第一个元素要从自己需要处理的元素开始算
function(arr,k+1);
swap(k, i);
}
}
}
private void swap(int i, int j) {
char c;
c = arr[i];
arr[i] = arr[j];
arr[j] = c;
}
void printHead(char[] arr){
for (int i = 0; i < arr.length-2; i++) {
System.out.print(arr[i]);
}
}
public static void main(String[] args) {
char[] arr = new char[] { '1', '2', '3' };
MyArrange3 a = new MyArrange3(arr);
a.function(arr,0);
}
}
//=========================================================================
C语言版
#include "stdio.h "
void perm(char arr[],int k,int len);
void swap(char *p,char *q);
char arr[]="1234";
void main(){
perm(arr,0,4);
}
void perm(char arr[], int k,int len){
if (k==len-2)
{
for (int j=0;j<len;j++)
{
printf("%c",arr[j] );
}
printf("\n" );
for (j=0;j<len-2;j++)
{
printf("%c",arr[j] );
}
printf("%c",arr[len-1] );
printf("%c",arr[len-2] );
printf("\n" );
}
else
{
for (int i=k;i<len;i++)
{
swap(&arr[k], &arr[i] );
perm(arr, k+1,len );
swap(&arr[k], &arr[i] );
}
}
}
void swap(char *p,char *q){
char c;
c=*p;
*p=*q;
*q=c;