递归公式给出多少排列?

时间:2018-11-20 17:22:31

标签: algorithm

是否有任何递归公式可以通过使用煎饼排序算法将n个煎饼的一定数量的翻转减少到有序排列,从而使排列数量减少到有序排列?

1 个答案:

答案 0 :(得分:1)

我没有证据,但是除非您限制翻转的次数很小,否则我愿意打赌没有这样的钱。

递归计算存在多少种执行翻转操作的方法没有问题。面临的挑战是,要弄清楚有多少其他方式可以通过不同的翻转顺序达到相同的顺序。实际上,对于每个https://en.wikipedia.org/wiki/Pancake_sorting#The_pancake_problems,找到最短的翻转序列以达到特定顺序都是NP难的。这意味着,如果您进行多次翻转,则用于识别何时发生另一次翻转的适当表达式将产生组合爆炸。


如果您希望选择排序算法可以n步骤来取消排列,则有一种方法可以以适合动态编程的方式递归计算。

f(n, m, on_top)是可以在n个步骤中解决的置换数量,其中m是最大的置换,而on_top是一个变量表示最大的错位是否在堆栈顶部。作为一种特殊情况,我们将说f(0, 0, True) = 1代表不需要排序的已排序堆栈。

现在我们的递归规则如下:

  1. 基本情况:f(0, 0, True) = 1
  2. 第二种基本情况:如果0 < n,则f(n, 0, False) = f(n, 0, True) = 0
  3. 第三种基本情况:如果0 < m,则f(0, m, True) = f(0, m, False) = 0
  4. 我们将最大的放在顶部的情况是:f(n, m, False) = (m-2) * f(n-1, m, True)。之所以这样,是因为第m个薄煎饼必须放在顶部m-1位置,因为它不合适,也没有更大的空间。但是它不能放在最前面,因为最后一个参数是True,而实际上不是。这样一来m-2就可能发生我们需要做的翻转。
  5. 在最大的位置放置f(n, m, True) = sum over i < m of (f(n-1, i, False) + f(n-1, i, True))。只是我们将最大的放到了原来的位置,然后提出了下一个最大的不放。

这足以让我们编写一个递归函数来计算答案。不幸的是,天真地计算该函数将涉及很多重复调用。但是,如果我们memoize通过保存您从一组参数中获得的值并在下次再次返回时来使用此函数,则您将缩短大部分计算的时间,并且评估该结果仅需使用多项式工作。