【问题标题】:Optimal algorithm for generating all combinations (order of letter matters) of a word生成单词的所有组合(字母顺序)的最佳算法
【发布时间】:2013-07-15 15:21:11
【问题描述】:

我正在寻找一种算法(最佳)来生成单词的所有可能组合。

例如:

给定love这个词,会输出以下内容:

生成的单词:24 叶洛夫 埃尔沃 欧尔夫 进化论 埃洛 进化 列夫 左旋 洛耶夫 爱 左旋 左旋 关注 oevl 奥列夫 橄榄 椭圆形 卵形 速度 元音 vleo 视频 声音 田鼠

给定单词bell(注意重复的l),将输出以下内容:

生成的单词:12 钟 贝尔 布尔 ebll elbl 埃尔布 贝尔 布尔 lebl 勒布 伊尔贝 乐乐

我有自己的算法来生成给定单词的所有组合。我基本上是在实现一个组合树。这是迄今为止更全面的,但它消耗大量的空间和时间。

【问题讨论】:

  • 什么是组合树?递归生成组合?
  • 也许您想按字典顺序对单词进行排序并尽可能应用一些“nextWord”功能?
  • 我认为更合适的术语是“多集排列”。 en.wikipedia.org/wiki/Permutation
  • 这个问题看起来很有希望:stackoverflow.com/questions/3467914/…。请注意,它不会生成所有排列,它会生成它们直到循环同构(

标签: algorithm tree word combinations permutation


【解决方案1】:
  1. 取单词中的字母总数 n,然后找到 n!。
  2. 计算每个字母出现的次数。对于每个重复多次的字母,除以(重复次数)!

示例: '香蕉'

2个n,3个a,共6个字母

答案 = 6!/(2!*3!) = 60

【讨论】:

    【解决方案2】:

    对于每个字符,可以通过将该字符与第一个字符交换并通过排除第一个字符进行递归来生成排列(不包括重复约束)。

    现在,如果我们想排除重复项,我们只需要确保我们不会将同一个字符放在第一个位置两次。这样做可以通过对字符进行排序(因此重复的字符彼此相邻)并跳过与之前的字符相同或与目标位置的字符相同的任何字符来完成。

    Java 代码:(源自a basic permutation generator

    import java.util.Arrays;
    import java.util.Scanner;
    
    public class NewMain
    {
       public static void main(String[] args)
       {
          Scanner sc = new Scanner(System.in);
          System.out.println("Enter the string:");
          String s = sc.nextLine();
          char[] c = s.toCharArray();
          Arrays.sort(c);
    
          System.out.println("Here are all the permutations:");
          NewMain.c = c;
          count = 0;
          permutation(0);
          System.out.println("Number of permutations = " + count);
       }
    
       static char[] c;
       static int count;
    
       static void swap(int pos1, int pos2)
       {
          char temp = c[pos1];
          c[pos1] = c[pos2];
          c[pos2] = temp;
       }
    
       public static void permutation(int start)
       {
          if (start == c.length)
          {
             System.out.println(c);
             count++;
          }
    
          for (int i = start; i < c.length; i++)
          {
             if (i == start || (c[i] != c[i-1] && c[i] != c[start]))
             {
                swap(start, i);
                permutation(start + 1);
                swap(start, i);
             }
          }
       }
    }
    

    Test.

    现在如果有太多个重复字符,这仍然不是特别有效。我能想到的一种改进方法是对每个字符进行计数(可能以链表(计数的链表)的形式,以便我们可以快速删除已达到 0 的计数,并插入它们之后返回),并且与上面类似,我们从左到右生成字符,通过在每个递归步骤仅处理每个计数一次来跳过重复项。

    【讨论】:

      【解决方案3】:

      很久之后,我终于得到了我的问题的答案。我使用 PHP 作为我的编程语言(因为它是我的选择,而不是其他任何东西)并且我使用了Pear Package: Math Combinatorics

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多