使用迭代接口的代码。时间复杂度为 O(n^2),空间复杂度的开销为:n 的副本(log n 位)、迭代变量(log n 位)、跟踪 ni(log n 位)、当前值的副本(log n 位)、p 的副本(n log n 位)、下一个值的创建(log n 位)和一组已使用值(n 位)。您无法避免 n log n 位的开销。时间上,这也是 O(n^2),用于设置位。这可以减少一点,但代价是使用装饰树来存储使用的值。
这可以通过调用适当的库来更改为使用任意精度的整数和位集,并且上述界限实际上将开始起作用,而不是被限制在 N=8,可移植(一个 int 可以与一个短的,小到 16 位)。9!= 362880 > 65536 = 2^16
#include <math.h>
#include <stdio.h>
typedef signed char index_t;
typedef unsigned int permutation;
static index_t permutation_next(index_t n, permutation p, index_t value)
{
permutation used = 0;
for (index_t i = 0; i < n; ++i) {
index_t left = n - i;
index_t digit = p % left;
p /= left;
for (index_t j = 0; j <= digit; ++j) {
if (used & (1 << j)) {
digit++;
}
}
used |= (1 << digit);
if (value == -1) {
return digit;
}
if (value == digit) {
value = -1;
}
}
/* value not found */
return -1;
}
static void dump_permutation(index_t n, permutation p)
{
index_t value = -1;
fputs("[", stdout);
value = permutation_next(n, p, value);
while (value != -1) {
printf("%d", value);
value = permutation_next(n, p, value);
if (value != -1) {
fputs(", ", stdout);
}
}
puts("]");
}
static int factorial(int n)
{
int prod = 1;
for (int i = 1; i <= n; ++i) {
prod *= i;
}
return prod;
}
int main(int argc, char **argv)
{
const index_t n = 4;
const permutation max = factorial(n);
for (permutation p = 0; p < max; ++p) {
dump_permutation(n, p);
}
}