您的位置:首页 > 其它

全排列(交换,递归,有详细解释)

2011-08-15 17:02 218 查看
这段话是网上抄来:

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;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: