注意:我之前删除了此帖子,因为我找到了以下post,但我不确定如何将其应用于我的问题。
我正在使用转置密码解码器。我已经解决了静态列的问题(1,2,3,4按顺序保存),但是我不知道如何创建一个长度的每个可能排列的数组(作为参数给出),I了解最简单的方法是某种递归方法,但在尝试这种方法时,我一直迷失在这种努力中。 (我整天都在编码而且很累)
示例数组将包含:
1,2,3,4,5,6
2,1,3,4,5,6
2,3,1,4,5,6
...
答案 0 :(得分:0)
经过一段时间的困惑,并尝试了一些不同的事情,我的一个朋友(这里不是用户)给了我以下的java解决方案:
if
答案 1 :(得分:0)
回想一下n!
项的n
个排列。 n!
可以通过以下方式轻松理解:
1. There are `n` options for choosing the first item.
2. There are `n-1` items remaining from which to choose the second item
...
n-1. There are `2` options left for the `n-1`-th item.
n. There is only 1 item left for the `n`-th position.
因此,如何订购商品总共有(n) * (n-1) * (n-2) * ... (2) * (1) = n!
个选项。
这直接揭示了使用混合基数编号方案枚举排列的方法。在此方案中,最重要的数字将为基数n
,下一个最重要的数字将为基数n-1
等。
使用这样的混合基数以下列方式选择排列:
[0, n-1]
,并且有n
个元素可供选择,因此您可以将其用作索引要选择的项目。)[0, n-2]
,并且还有n-1个数字)如果我们使用数组来表示little-endian数字顺序的混合基数,那么我们将得到以下结果:
int mixed_radix[n] = {0};
您可以通过以下方式递增此混合基数:
//Increment the least-significant digit
mixed_radix[0]++;
//Ripple overflow toward the most-significant digit
for(i=0; i<n; i++) {
if(mixed_radix[i] > i) {
mixed_radix[i] = 0;
if(i < n-1)mixed_radix[i+1]++;
}
else {
break;
}
}
因此我们有办法将混合基数编号初始化为零,然后将其递增到每个可能的值,一旦它回绕到零就停止。 (或n!-1
递增后......)
所有这一切,有一个可爱的数字技巧可以使这更简单:你可以通过以下方式从整数解压缩那个丑陋的混合基数:
我们知道n!
个项目有n
个排列;对于val
范围内的任何整数[0, n!-1]
,下面提供了整数值和混合基数之间的双射映射:
int working = val; //val in the range [0, n!-1]
for(j=0 j<n; j++) {
mixed_radix[j] = working % (j+1);
working /= (j+1);
}
所以嵌入这个&#34;拆包&#34;在val
到0
范围内运行n!-1
的外循环内循环是一个更密集的方法来枚举混合基数(枚举可能的排列)。它还为每个排列分配一个整数,有效地命名它们。 :)