这是《编程之美》中的一道题,以下是我的学习心得。
一,问题:
问题的关键是,单手每次抓几块饼,全部颠倒。具体参考如图1-1所示
变为
图1-1
每次只能选择最上方的一堆饼,一起翻转,而不能一张张的直接抽出来,然后进行插入,也不能交换任意两块饼。
图1-2演示一下,为了把最大的烙饼摆在最下面,先把最上面的和最大的烙饼之间翻转,这样,最大的烙饼就在最上面了。接着,把所有烙饼翻转,最大的烙饼在最下面了。
变为
变为
图1-2
这是一特殊的例子,经过两次翻转即实现了。两次翻转就可以把最大的烙饼翻转到最下面。因此,最多需要把上面的n-1个烙饼依次翻转两次。那么我们至多需要2(n-1)次翻转就可以把所有烙饼排好序。
单手翻转可以实现,进一步想,怎样减少翻转烙饼的次数呢。
考虑这样一种情况,假如这堆烙饼中有好几个不同的部分相对有序,凭直觉来猜,可以先把小的烙饼进行翻转,让其有序,这样会比每次翻转最大的烙饼要更快。
把两个本来应该相邻的烙饼尽可能地换到一起。这样,等所有烙饼都换到一起之后,实际上就是完成排序了。(从这个医院上讲,每次翻转最大烙饼的方案实质上就是每次把最大的和次大的交换到一起)
在这个基础上,本能的想法是穷举。只要穷举出所有可能的交换方案,那么,我们一定能找到最优的一个。
沿着这个思路,我们自然用动态规划或递归的方法实现,可以从不同的翻转策略开始,比如第一次翻转最小的,然后递归把所有的可能全部翻转一遍,这样,最终肯定是可以找到一个解的。
递归的退出条件是什么呢?第一个退出条件是所有烙饼已经排好序。既然2(n-1)是一个最多的翻转次数,那么在算法中,需要翻转次数多于2(n-1),我们就应该放弃这个方案。