用于生成单词的所有组合(字母顺序)的最佳算法

时间:2013-07-17 07:20:24

标签: algorithm tree word combinations permutation

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

例如:

  
    

鉴于这个词,将输出以下内容:

         
      

生成的单词:24       elov       ELVO       eolv       eovl       器EV10       EVOL       leov       左旋       loev       爱       lveo       lvoe       oelv       oevl       OLEV       olve       OVEL       ovle       VELO       VEOL       vleo       vloe       voel       田鼠

    
         

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

         
      

生成的单词:12       钟       BLEL       blle       ebll       ELBL       ellb       lbel       lble       LEBL       lelb       llbe       lleb

    
  

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

3 个答案:

答案 0 :(得分:1)

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

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

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的计数,然后插入它们之后回来),与上面类似,我们从左到右生成字符,跳过重复项,只在每个递归步骤处理一次计数。

答案 1 :(得分:1)

  1. 取字n中的字母总数,找到n!。
  2. 计算每个字母的出现次数。对于每次重复不止一次的字母,除以(重复次数)!
  3. 实施例: '香蕉'

    2个,3个,6个字母

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

答案 2 :(得分:0)

经过很长一段时间,我终于得到了一个问题的答案。我使用PHP作为我的编程语言(因为这是我的选择而不是其他任何东西)而且我使用了Pear Package: Math Combinatorics