打印全排列
打印出一个字符串的全排列,有很多方法,最容易看到的是递归的方法。
void range(char a[], int k){
if(k==a.length-1){
System.out.println(Arrays.toString(a));
}
else {
for(int i=k;i<a.length;i++){
swap(a[i],a[k]);
range(a,k+1);
swap(a[k],a[i]);
}
}
还可以借助栈来把上面的改成非递归。
当然还有其他的方法,比如
1、字典序方法。
写的时候借助一个Num[]辅助数组。
void printRange(char a[]){
for(int i=0;i<a.length;i++){
num[i]=i;
}
while(hasNext(num)){
print(a,num);
moveNext(num);
}
------
比如abc对应辅助数组初始状态是012,当num变成210是hasNext(num)为false;
当怎样从012生成下一个呢?
比如124653,我们要找到它的下一个数字串,使用的方法是
1、从右到左扫描,找到一个位置,num[pos]<num[pos+1],然后从pos+1向后扫描,在所有大于num[pos]的数字当中找到一个最小的,记录位置k,
然后交换num[pos]和num[k]
2 之后,将pos+1~n-1位置的字符互换, 即reverse the substring from pos+1 to n-1.
另外一种方法叫做进制递增法。
http://llfclz.itpub.net/post/1160/278490
设想有 n 个数字, 先取第一个数字. 再取第二个数字, 第二个数可以放在第一个数的左或右面, 就是有 0, 1 两个选择. 再取第三个数, 放到前面选好的两个数字中, 可以放在最左, 中间, 最右, 就是有 0, 1, 2 三个选择. 嗯, 很自然吗. 忽然你想到了二进位, 八进位那些数系转换关系。可以设计这样一个数, ...xyz, 其中个位数 z 是二进位的, 也就是放第二个数的两个位置; 十位数 y 是三进位的, 代表放第三个数字的三个位子, 然后百位数是四进位, 千位数是五进位的, 依以类推." 没错, 这样设计的话, 如果 0 表示放於最左面的话, 则 "2021" 这个数就代表了排列五个元素 (abcde), 取一个 a, 然后第二个 b 放在 a 的右面成 ab, 取 c 放到最右面成为 abc, 取 d 放到最左面成 dabc; 最后 e 放到中间去成为 daebc. 至於 "2021" 这个特别的设计的数可以用2*5+ 0*4 + 2*3 + 1*2 这样的计算来映对到自然数的数列上去。
如求 4 个数的 4! = 24 个排列, 第 18 个排列可以这样求得, 18 除 2, 余数是 0, 所以第二个数放在第一个数的左面; 然后商 9 再除 3, 余数 0,所以第三个数於在头两个数的最左; 最后 3 除以 4, 余数是 3, 因此第四个数要放在前三个数的第 4 个空位, 也就是最右面。
1 import java.util.Arrays; 2 import java.util.Scanner; 3 4 /* A!全排列 5 * Algorithm Description 6 * 进制递增 7 * 8 */ 9 public class Al2 { 10 private int factorial(int n){ 11 int sum=1; 12 for(int i=1;i<=n;i++){ 13 sum*=i; 14 } 15 return sum; 16 } 17 private void insert(int pos, char ch, char []cArr){ 18 if(cArr[pos]!=' '){ 19 for(int i=cArr.length-1;i>pos;i--){ 20 cArr[i]=cArr[i-1]; 21 } 22 cArr[pos]=ch; 23 } else{ 24 cArr[pos]=ch; 25 } 26 } 27 private void solve(String str){ 28 int n=str.length(); 29 int m=factorial(n); 30 int []num=new int[n-1]; 31 char []cArr=new char[n]; 32 int i,j; 33 for(i=0;i<m;i++){ 34 Arrays.fill(cArr, ' '); 35 cArr[0]=str.charAt(0); 36 int c=i; 37 for(j=2;j<=n;j++){ 38 num[j-2]=c%j; 39 c=c/j; 40 } 41 //System.out.print(Arrays.toString(num)+" "); 42 for(j=0;j<n-1;j++){ 43 insert(num[j],str.charAt(j+1),cArr); 44 } 45 //System.out.println("i="+(i+1)+": "+Arrays.toString(cArr)); 46 } 47 } 48 public static void main(String args[]){ 49 Scanner sc=new Scanner(System.in); 50 long startTime=System.currentTimeMillis(); 51 new Al2().solve(sc.nextLine()); 52 long endTime=System.currentTimeMillis(); 53 System.out.println("Time cost: "+(endTime-startTime)); 54 } 55 }