提高给定字符串所有排列的时间复杂度

Improving the time complexity of all permutations of a given string

本文关键字:排列 时间复杂度 字符串      更新时间:2023-10-16

这个问题通常被提出为给定一个字符串,打印它的所有排列。例如,字符串ABC的排列是ABC,ACB,BAC,BCA,CAB,CBA。

标准解决方案是递归解决方案,如下所示。

void permute(char *a, int i, int n) 
{
   int j; 
   if (i == n)
     printf("%sn", a);
   else
   {
        for (j = i; j <= n; j++)
       {
          swap((a+i), (a+j));
          permute(a, i+1, n);
          swap((a+i), (a+j)); //backtrack
       }
   }
}

这,遇到了O(n*n!).这是我们能做的最好的事情,还是有办法让它更快?

您可以使用std::next_permutation .请注意,它仅在排序数组上正常工作。
此解决方案的优点:1)它是标准的2)它是非递归的

下面是一个示例 (http://www.cplusplus.com/reference/algorithm/next_permutation/):

// next_permutation example
#include <iostream>     // std::cout
#include <algorithm>    // std::next_permutation, std::sort
int main () {
  int myints[] = {1, 2, 3};
  std::sort (myints, myints + 3);
  std::cout << "The 3! possible permutations with 3 elements:n";
  do {
    std::cout << myints[0] << ' ' << myints[1] << ' ' << myints[2] << 'n';
  } while (std::next_permutation (myints, myints + 3));
  std::cout << "After loop: " << myints[0] << ' ' << myints[1] << ' ' << myints[2] << 'n';
  return 0;
}

您正在寻找的结果包含 n*n 个元素,所以这是你能得到的最好的!

假设您有n元素,并且正在寻找k个排列0 <= k <= n-1

  • 创建一个包含所有元素和空列表result的列表elements
  • while elements not empty
    • 设置p = k % elements.sizek = k / elements.size
    • 删除elements[p]并将其附加到result

我们只访问elements的每个元素一次,所以它是 O(n)。

std::next_permutation可以完成这项工作:

#include <algorithm>
#include <iostream>
int main () {
    char s[] = "BAC";
    // let's begin with the lowest lexicographically string.
    std::sort(std::begin(s), std::end(s) - 1); // '- 1' : ignore ''
    do {
        std::cout << s << std::endl;
    } while (std::next_permutation(std::begin(s), std::end(s) - 1));
  return 0;
}