【问题标题】:Algorithm to list unique permutations of string with duplicate letters列出具有重复字母的字符串的唯一排列的算法
【发布时间】:2017-04-06 17:53:55
【问题描述】:

例如,字符串“AAABBB”将有排列: “阿巴布”, “巴巴巴”, “阿巴巴”, 等等

什么是生成排列的好算法? (它的时间复杂度是多少?)

【问题讨论】:

  • 生成所有排列将花费你 O(n!) 其中 n 是字符串的长度。
  • @KaranNagpal:不会。它会小于n!,并且取决于重复字母的数量。在AAABBB 示例中,有 20 个唯一排列,而不是 720 个。
  • 是的,20 = 6!/(3!*3!) ...您可以通过取长度的阶乘除以每个字母出现的阶乘得到排列的数量。
  • 也可以使用位图来优化空间复杂度

标签: algorithm permutation


【解决方案1】:

对于多集,可以通过位置递归求解(JavaScript 代码):

function f(multiset,counters,result){
  if (counters.every(x => x === 0)){
    console.log(result);
    return;
  }

  for (var i=0; i<counters.length; i++){
    if (counters[i] > 0){
      _counters = counters.slice();
      _counters[i]--;
      f(multiset,_counters,result + multiset[i]);
    }
  }
}

f(['A','B'],[3,3],'');

【讨论】:

    【解决方案2】:

    这不是完整的答案,只是一个想法。

    如果您的字符串只有两个字母,我将使用二叉树和良好的递归函数。 每个节点都是包含名称的对象,名称带有父名称前缀和后缀 A 或 B,并且名称中包含 A 和 B 字母的数量。

    节点构造函数从父节点获取父节点的名称和 A 和 B 的数量,因此它只需要在 A 或 B 的数量上加 1 并在名称上加一个字母。

    如果A(在A节点的情况下)或B分别超过三个,或者它们的总和等于起始字符串的长度,则不构造下一个节点。

    现在您可以收集 2 棵树的叶子(它们的名称),并拥有您需要的所有排列。

    Scala 或一些函数式语言(具有类似对象的特性)非常适合实现该算法。希望这会有所帮助,或者只是激发一些想法。

    【讨论】:

      【解决方案3】:

      由于您实际上想要生成排列而不是仅仅计算排列,因此您可以期望的最佳复杂度是 O(size_of_output)。

      这是一个很好的 java 解决方案,它满足了这个限制并且运行得非常快,同时占用的空间可以忽略不计。它首先对字母进行排序以找到按字典顺序排列的最小排列,然后按字典顺序生成所有排列。

      它被称为 Pandita 算法:https://en.wikipedia.org/wiki/Permutation#Generation_in_lexicographic_order

      import java.util.Arrays;
      import java.util.function.Consumer;
      
      
      public class UniquePermutations
      {
          static void generateUniquePermutations(String s, Consumer<String> consumer)
          {
              char[] array = s.toCharArray();
              Arrays.sort(array);
              for (;;)
              {
                  consumer.accept(String.valueOf(array));
      
                  int changePos=array.length-2;
                  while (changePos>=0 && array[changePos]>=array[changePos+1])
                      --changePos;
      
                  if (changePos<0)
                      break; //all done
      
                  int swapPos=changePos+1;
                  while(swapPos+1 < array.length && array[swapPos+1]>array[changePos])
                      ++swapPos;
      
                  char t = array[changePos];
                  array[changePos] = array[swapPos];
                  array[swapPos] = t;
      
                  for (int i=changePos+1, j = array.length-1; i < j; ++i,--j)
                  {
                      t = array[i];
                      array[i] = array[j];
                      array[j] = t;
                  }
              }
          }
      
          public static void main (String[] args) throws java.lang.Exception
          {
              StringBuilder line = new StringBuilder();
              generateUniquePermutations("banana", s->{
                  if (line.length() > 0)
                  {
                      if (line.length() + s.length() >= 75)
                      {
                          System.out.println(line.toString());
                          line.setLength(0);
                      }
                      else
                          line.append(" ");
                  }
                  line.append(s);
              });
              System.out.println(line);
          }
      }
      

      这是输出:

      aaabnn aaanbn aaannb aabann aabnan aabnna aanabn aananb aanban aanbna
      aannab aannba abaann abanan abanna abnaan abnana abnnaa anaabn anaanb
      anaban anabna ananab ananba anbaan anbana anbnaa annaab annaba annbaa
      baaann baanan baanna banaan banana bannaa bnaaan bnaana bnanaa bnnaaa
      naaabn naaanb naaban naabna naanab naanba nabaan nabana nabnaa nanaab
      nanaba nanbaa nbaaan nbaana nbanaa nbnaaa nnaaab nnaaba nnabaa nnbaaa
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-07-16
        • 2018-10-09
        相关资源
        最近更新 更多