如何在O(n)中进行K个循环置换

时间:2019-05-05 06:09:13

标签: c++

我需要在left或right处进行K个圆排列。我只想要一个向我展示从哪里开始向量生成的公式。我需要一个用于左圆排列,一个用于右圆排列。

1 个答案:

答案 0 :(得分:0)

对于K项列表,有K!个可能的排列(非圆形)。我们将在一秒钟内进行循环排列。

为大小为K的数组和从[0..K)开始的排列索引生成特定的排列(有效索引为0到k-1)。您可以执行以下操作:

// this is pseudo-code that happens to resemble java
void permute(long [] permutation, long count, long permutationIndex)
{
    for (long c = 0; c < count; c++)
    {
        permutation[c] = c;
    }

    for (long i = 0; i < count; i++)
    {
        long srcindex = i;
        long dstindex = i + permutationIndex % (count - i);

        // swap
        if (srcindex != dstindex)
        {
            long tmp = permutation[srcindex];
            permutation[srcindex] = permutation[dstindex];
            permutation[dstindex] = tmp;
        }
        permutationIndex /= (count - i);
    }
}

然后打印任何给定数组的所有排列:

void print_all_permutations(Items [] items)
{
     int len = items.length;

     long [] indices = new long[len];
     long count = factorial(len);
     for (long p = 0; p < count; p++)
     {
         permute(indices, len, p);
         for (j = 0; j < len; j++)
         {
             print(items[indices[j]]);
         }
         printNewLine();
     }
}

现在,循环排列如何?这很容易。只需将一项保留在固定位置,然后置换数组的其余部分即可:

void print_all_permutations(Items [] items)
{
     Item fixed = items[items.length-1];

     int len = items.length-1;

     long [] indices = new long[len];
     long count = factorial(len);
     for (long p = 0; p < count; p++)
     {
         permute(indices, len, p);
         for (j = 0; j < len; j++)
         {
             print(items[indices[j]]);
         }
         print(fixed); // print the fixed item last
         printNewLine();
     }
}