zoukankan      html  css  js  c++  java
  • 打印全排列

    打印出一个字符串的全排列,有很多方法,最容易看到的是递归的方法。

    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 }

     

     

  • 相关阅读:
    进程及进程调度
    加强版水王:找出出现次数刚好是一半的数字
    寻找最小的k个数(四种方法)
    Count Primes
    深入理解计算机系统结构——并发编程
    深入理解计算机系统——系统级I/O
    深入理解计算机系统结构——虚拟存储器
    老生常谈:关于undo表空间的使用率
    OSW 快速安装部署
    Oracle参数设置之set与reset的实际案例
  • 原文地址:https://www.cnblogs.com/gaoqichao/p/2600001.html
Copyright © 2011-2022 走看看