zoukankan      html  css  js  c++  java
  • 字符串的排列和组合问题

    1、字符串的全排列

    题目:{a,b,c}要求输出{abc,acb,bac,bca,cab,cba}。

    字符串全排列可以把字符串看成两个部分,第一个部分为它的一个字符,第二部分是后面的字符。

    分两步完成:首先求所有可能出现在第一个位置的字符,即把第一个字符与后面的所有字符交换。第二步固定第一个字符,求后面所有字符的排列。从中可以看出是典型的递归思路。 

     1     public void helper(char[] array, int cur){
     2         if ( cur == array.length - 1 ) print(array);
     3         else {
     4             for ( int i = cur ; i < array.length ; i ++ ){
     5                 swap(array,cur,i);
     6                 helper(array,cur+1);  //固定第一个字符,对后面所有字符全排列
     7                 swap(array,i,cur);
     8             }
     9         }
    10     }

    如果给的字符中出现重复,即{a,b,c,c}这种情况,可以判断当前准备交换的字符,如果当前准备交换的字符已经在cur前面的字符中出现过了,就跳过,否则就交换。修改后方法如下:

     1     public void helper(char[] array, int cur){
     2         if ( cur == array.length - 1 ) print(array);
     3         else {
     4             for ( int i = cur ; i < array.length ; i ++ ) {
     5                 if (!isExit(array, cur, i)) {
     6                     swap(array, cur, i);
     7                     helper(array, cur + 1);  //固定第一个字符,对后面所有字符全排列
     8                     swap(array, i, cur);
     9                 }
    10             }
    11         }
    12     }
    13     private boolean isExit(char[] array, int cur, int i) {
    14         for ( int k = cur ; k < i ; k ++ ){
    15             if ( array[k] == array[i] ) return true;
    16         }
    17         return false
    18     }

    2、字符串组合

    题目:{a,b,c}要求输出{a,b,c,ab,ac,bc,abc}。

    分析,可以将题目分成小问题来理解,1个字符的组合+2个字符的组合+3个字符的组合,因此我们只要找到一般的方法,即从n个字符中找m个字符的组合就可以了。

    我们可以把n个字符分成两部分,第一个字符和其他所有字符。如果组合里包含第一个字符,则下一步在剩余的字符里选取m-1个字符;如果组合里不包含第一个字符,则下一步在剩余的n-1个字符里选取m个字符,从中可以看出又是个递归的过程。

     1     Stack<Character> stack = new Stack<>();
     2     public void helper(char[] array){
     3         for ( int i = 1 ; i <= array.length ; i ++ )
     4             combination(array,0,i);
     5     }
     6     private void combination(char[] strArr, int begin, int num) {
     7         if (num == 0) {
     8             System.out.println(stack);
     9             return;
    10         }
    11         if (begin >= strArr.length) {
    12             return;
    13         } else {
    14             //把第一个字符放入组合中,在剩余的字符中选取num-1个字符
    15             stack.push(strArr[begin]);
    16             combination(strArr, begin + 1, num - 1);
    17             //组合里不包含第一个字符,则下一步在剩余的字符中选取num个字符
    18             stack.pop();
    19             combination(strArr, begin + 1, num);
    20         }
    21     }

    helper函数表示求长度为i的全排列。

    还有一种更nb的方法,因为组合问题,比如3个元素的组合就有2^3-1种,所以不妨给他们进行编号,就像上面的问题,从a——abc一次编号为 001——111。1就代表该位置出现字符。例如:001->c,010->b,101->ac......,所以原题就是要求输出"001"-"111"这2^n-1个组合对应的字符串。

     1 public static void main(String[] args) {
     2 
     3   String s = "abc";
     4   ArrayList<String> result = combineString(s);
     5   for(String r : result){
     6     System.out.println(r);
     7   }
     8 }
     9 
    10 private static ArrayList<String> combineString(String s) {
    11   int len = s.length();
    12   ArrayList<String> list = new ArrayList<String>(); 
    13   int count = (int) (Math.pow(2, len));
    14   for(int i = 1; i < count; ++i){
    15     String temp = "";
    16     String str = Integer.toBinaryString(i);
    17     while(str.length() < len){
    18       str = "0" + str;
    19     }
    20     for(int j = 0; j < str.length(); ++j){
    21       if(str.charAt(j) == '1'){
    22         temp += s.charAt(j);
    23       }
    24     }
    25     list.add(temp);
    26   }
    27   return list;
    28 }
  • 相关阅读:
    B
    B
    G
    F
    E
    A
    C
    2017icpc 乌鲁木齐网络赛
    bzoj 2038 小Z的袜子(hose)(莫队算法)
    矩阵快速幂刷题系列
  • 原文地址:https://www.cnblogs.com/boris1221/p/9388209.html
Copyright © 2011-2022 走看看