【问题标题】:Smart way to generate permutation and combination of String生成字符串排列组合的智能方法
【发布时间】:2013-11-28 08:58:00
【问题描述】:
String database[] = {'a', 'b', 'c'};

我想根据给定的database 生成以下字符串序列。

a
b
c
aa
ab
ac
ba
bb
bc
ca
cb
cc
aaa
...

我只能想到一个相当“愚蠢”的解决方案。

public class JavaApplication21 {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        char[] database = {'a', 'b', 'c'};

        String query = "a";
        StringBuilder query_sb = new StringBuilder(query);
        for (int a = 0; a < database.length; a++) {
            query_sb.setCharAt(0, database[a]);
            query = query_sb.toString();                    
            System.out.println(query);            
        }

        query = "aa";
        query_sb = new StringBuilder(query);
        for (int a = 0; a < database.length; a++) {
            query_sb.setCharAt(0, database[a]);    
            for (int b = 0; b < database.length; b++) {    
                query_sb.setCharAt(1, database[b]);    
                query = query_sb.toString();                    
                System.out.println(query);
            }
        }

        query = "aaa";
        query_sb = new StringBuilder(query);
        for (int a = 0; a < database.length; a++) {
            query_sb.setCharAt(0, database[a]);    
            for (int b = 0; b < database.length; b++) {    
                query_sb.setCharAt(1, database[b]);    
                for (int c = 0; c < database.length; c++) {                    
                    query_sb.setCharAt(2, database[c]);                        
                    query = query_sb.toString();                    
                    System.out.println(query);
                }
            }
        }
    }
}

解决方案非常愚蠢。从某种意义上说,它是不可扩展的

  1. 如果我增加database 的大小会怎样?
  2. 如果我的最终目标打印字符串长度需要为 N 怎么办?

是否有任何智能代码可以以非常智能的方式生成可扩展的排列和组合字符串?

【问题讨论】:

  • 在Python中,很简单,哈哈。 print ''.join(query) for query in itertools.combinations_with_replacement(database, length) for length in range(1,N+1)

标签: java algorithm combinations permutation


【解决方案1】:

你应该检查这个答案:Getting every possible permutation of a string or combination including repeated characters in Java

获取此代码:

public static String[] getAllLists(String[] elements, int lengthOfList)
{

    //lists of length 1 are just the original elements
    if(lengthOfList == 1) return elements; 
    else {
        //initialize our returned list with the number of elements calculated above
        String[] allLists = new String[(int)Math.pow(elements.length, lengthOfList)];

        //the recursion--get all lists of length 3, length 2, all the way up to 1
        String[] allSublists = getAllLists(elements, lengthOfList - 1);

        //append the sublists to each element
        int arrayIndex = 0;

        for(int i = 0; i < elements.length; i++){
            for(int j = 0; j < allSublists.length; j++){
                //add the newly appended combination to the list
                allLists[arrayIndex] = elements[i] + allSublists[j];
                arrayIndex++;
            }
        }
        return allLists;
    }
}

public static void main(String[] args){
    String[] database = {"a","b","c"};
    for(int i=1; i<=database.length; i++){
        String[] result = getAllLists(database, i);
        for(int j=0; j<result.length; j++){
            System.out.println(result[j]);
        }
    }
}

虽然可以进一步改进内存,因为这个解决方案首先生成内存的所有解决方案(数组),然后我们才能打印它。但是思路是一样的,就是使用递归算法。

【讨论】:

  • 一个小评论:allLists 初始化最好在 else (main) case 中移动
  • @almondandapricot 更新了!
【解决方案2】:

这闻起来像二进制数:

  • 001
  • 010
  • 011
  • 100
  • 101
  • ...

我的第一直觉是使用二进制计数器作为字符的“位图”来生成那些可能的值。但是,这里有几个关于建议使用递归的相关问题的精彩答案。见

【讨论】:

  • 这是正确的,但aa 是一个有效的排列。
  • 我认为除了使用二进制之外,还可以使用更高的基数轻松完成。因为他有三个元素,所以可以在 base 3 中完成
  • 仍然无法扩展...下次他在database 中有四个元素。但你越来越近了……
  • 好吧,如果他的数据库中有 n 个元素,他可以在基数 n 中做到这一点
  • “如果他的数据库中有 n 个元素,他可以以 n 为基数” -> 这正是 OP 所要求的。哈哈
【解决方案3】:

排列生成器的 Java 实现:-

public class Permutations {


    public static void permGen(char[] s,int i,int k,char[] buff) {
        if(i<k) {
            for(int j=0;j<s.length;j++) {

                buff[i] = s[j];
                permGen(s,i+1,k,buff);
            }
        }       
        else {

         System.out.println(String.valueOf(buff)); 

        }

    }

    public static void main(String[] args) {
        char[] database = {'a', 'b', 'c'};
        char[] buff = new char[database.length];
        int k = database.length;
        for(int i=1;i<=k;i++) {
            permGen(database,0,i,buff);
        }

}

}

【讨论】:

    【解决方案4】:

    好的,所以排列的最佳解决方案是递归。假设字符串中有 n 个不同的字母。这将产生 n 个子问题,每个子问题对应于从每个唯一字母开始的每组排列。创建一个方法permutationsWithPrefix(String thePrefix, String theString) 来解决这些个别问题。创建另一个方法listPermutations(String theString) 实现类似于

    void permutationsWithPrefix(String thePrefix, String theString) {
       if ( !theString.length ) println(thePrefix + theString);
       for(int i = 0; i < theString.length; i ++ ) {
          char c = theString.charAt(i);
          String workingOn = theString.subString(0, i) + theString.subString(i+1);   
          permutationsWithPrefix(prefix + c, workingOn);
       }
    } 
    
    void listPermutations(String theString) {
       permutationsWithPrefix("", theString);
    }
    

    【讨论】:

      【解决方案5】:

      我遇到了这个问题作为面试问题之一。以下是我使用递归针对此问题实施的解决方案。

      public class PasswordCracker {
      
      private List<String> doComputations(String inputString) {
      
          List<String> totalList =  new ArrayList<String>();
          for (int i = 1; i <= inputString.length(); i++) {
      
              totalList.addAll(getCombinationsPerLength(inputString, i));
          }
          return totalList;
      
      }
      
      private ArrayList<String> getCombinationsPerLength(
              String inputString, int i) {
      
          ArrayList<String> combinations = new ArrayList<String>();
      
          if (i == 1) {
      
              char [] charArray = inputString.toCharArray();
              for (int j = 0; j < charArray.length; j++) {
                  combinations.add(((Character)charArray[j]).toString());
              }
              return combinations;
          }
          for (int j = 0; j < inputString.length(); j++) {
      
              ArrayList<String> combs = getCombinationsPerLength(inputString, i-1);
              for (String string : combs) {
                  combinations.add(inputString.charAt(j) + string);
              }
          }
      
          return combinations;
      }
      public static void main(String args[]) {
      
          String testString = "abc";
          PasswordCracker crackerTest = new PasswordCracker();
          System.out.println(crackerTest.doComputations(testString));
      
      }
      }
      

      【讨论】:

        【解决方案6】:

        对于任何寻找非递归选项的人,这里有一个数字排列示例(可以很容易地适应charnumberOfAgents 是列数,数字集是 0numberOfActions

            int numberOfAgents=5;
            int numberOfActions = 8;
            byte[][]combinations = new byte[(int)Math.pow(numberOfActions,numberOfAgents)][numberOfAgents];
        
            // do each column separately
            for (byte j = 0; j < numberOfAgents; j++) {
                // for this column, repeat each option in the set 'reps' times
                int reps = (int) Math.pow(numberOfActions, j);
        
                // for each column, repeat the whole set of options until we reach the end
                int counter=0;
                while(counter<combinations.length) {
                    // for each option
                    for (byte i = 0; i < numberOfActions; i++) {
                        // save each option 'reps' times
                        for (int k = 0; k < reps; k++)
                            combinations[counter + i * reps + k][j] = i;
                    }
                    // increase counter by 'reps' times amount of actions
                    counter+=reps*numberOfActions;
                }
            }
        
            // print
            for(byte[] setOfActions : combinations) {
                for (byte b : setOfActions)
                    System.out.print(b);
                System.out.println();
            }
        

        【讨论】:

          【解决方案7】:
          // IF YOU NEED REPEATITION USE ARRAYLIST INSTEAD OF SET!!
          
          import java.util.*;
          public class Permutation {
          
              public static void main(String[] args) {
                  Scanner in=new Scanner(System.in);
                  System.out.println("ENTER A STRING");
                  Set<String> se=find(in.nextLine());
                  System.out.println((se));
              }
              public static Set<String> find(String s)
              {
                  Set<String> ss=new HashSet<String>();
                  if(s==null)
                  {
                      return null;
                  }
                  if(s.length()==0)
                  {
                      ss.add("");
                  }
                  else
                  {
                      char c=s.charAt(0);
                      String st=s.substring(1);
                      Set<String> qq=find(st);
                      for(String str:qq)
                      {
                          for(int i=0;i<=str.length();i++)
                          {
                              ss.add(comb(str,c,i));
                          }
                      }
                  }
                  return ss;
          
              }
              public static String comb(String s,char c,int i)
              {
                  String start=s.substring(0,i);
                  String end=s.substring(i);
                  return start+c+end;
              }
          
          }
          
          
          // IF YOU NEED REPEATITION USE ARRAYLIST INSTEAD OF SET!!
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-12-02
            • 1970-01-01
            • 1970-01-01
            • 2011-10-18
            相关资源
            最近更新 更多