tri*_*cot 10 algorithm permutation combinatorics
是否有算法可以找到一系列独特元素的所有可能排列,遵循此规则?
从给定的排列中,必须通过正好循环3个元素来找到下一个排列.它们可以是任何三个元素.
对于这样的3个循环,将仅找到所有排列的子集,但是应该找到可能通过3个循环到达的所有排列,并且在找到所有可到达的排列之前不应找到相同的排列两次.
这是一个示例输入:
1,2,3,4,5
Run Code Online (Sandbox Code Playgroud)
输出可能是:
3,1,2,4,5
2,3,1,4,5
4,2,1,3,5
3,4,1,2,5
1,3,4,2,5
4,1,3,2,5
2,4,3,1,5
Run Code Online (Sandbox Code Playgroud)
...等
我试图产生这样一个序列的众多算法之一如下(对于数组a和长度为n):
print (a)
for i = 0 to n-1
for j = i+1 to n-1
for l = j+2 to n-1
for k = j+1 to l
cycle a[i],a[j],a[k]
print (a)
cycle a[i],a[j],a[k]
print (a)
Run Code Online (Sandbox Code Playgroud)
这产生了上面印刷的系列,但接着继续:
1,2,3,4,5
Run Code Online (Sandbox Code Playgroud)
..这是已经输出的排列.到目前为止我找到的任何其他寻找下一个3周期的算法都未能找到所有可达到的排列.
有这篇旧报纸VL Kompel'makher和VA Liskovets.通过换位顺序生成排列.,这表明您可以通过简单的换位生成所有排列,并且每个转置必须将排列的第一个元素与任何其他排列交换(所谓的星形基础).例如,对于S(3),因为第一个元素(与元素1相对)在每个步骤中交换.
123->213->312->132->231->321->[123, Hamiltonian cycle!]
Run Code Online (Sandbox Code Playgroud)
还有一种类似的方法A"Hot Potato"灰色代码用于排列,它不在付费墙后面.本文的一个重要见解是,即使必须交换每个转置元素1,仍然可以生成所有排列而不重复(每一步都交换元素1):
123->213->231->132->312->321->[123, Hamiltonian cycle!]
Run Code Online (Sandbox Code Playgroud)
循环通过星形基础的所有排列的另一种算法是来自Knuths的"计算机编程的艺术",章节"生成所有排列".算法被称为"Ehrlich交换方法".我没有声称要了解那里发生了什么,它只是将算法转换为java.最有趣的部分是这一行:
//swap values to get next permutation:
swap(per,0,b[k]);
Run Code Online (Sandbox Code Playgroud)
在每个步骤中都有一个转置,并且在每个转置中,元素[0]被交换( - >星形基础).
import java.util.Arrays;
public class EhrlichPermuter {
//Follows Knuths "The Art of computer programming", Chapter "Generating all permutations", "Ehrlich's swap method".
int n;
int[] c;
int[] b;
int[] per;
boolean done;
void initialize(){
c=new int[n];
b=new int[n];
per=new int[n];
for(int j=0;j<n;j++){
b[j]=j;
per[j]=j;
}
}
EhrlichPermuter(int n){
this.n=n;
initialize();
}
void swap(int[] a, int i, int j){
int h=a[i];a[i]=a[j];a[j]=h;
}
int[] getNextPermut(){
int[] result=Arrays.copyOf(per, per.length);//remember permutation
int k=1;
while(c[k]>=k){
c[k]=0;
k++;
if(k==n){
done=true;
initialize();//we got all permutations so far
return result;//return the last permutation
}
}
c[k]=c[k]+1;
//swap values to get next permutation:
swap(per,0,b[k]);
//flip:
int j=1; k--;
while(j<k){
swap(b,j,k);
j++;
k--;
}
return result;//return remembered permutation
}
}
Run Code Online (Sandbox Code Playgroud)
现在硬盘已经完成了!
最后一步是:形式(1a)(1b)的任何两个连续转置可以写为3元素循环(1ab).因此,您只需跳过具有负奇偶校验的排列.对于Hot-Potato,这看起来如下
123 --(213)-->231--(132)-->312--(321)-->[123, Hamiltonian cycle!]
Run Code Online (Sandbox Code Playgroud)
排除()中的排列.