您的位置:首页 > 其它

一摞饼的排序

2015-12-13 17:04 260 查看
这是《编程之美》中的一道题,以下是我的学习心得。

一,问题:



星期五的晚上,一帮同事在希格玛大厦附近的“硬盘酒吧”多喝了几杯。程序员多喝了几杯之后谈什么呢?自然是算法问题。有个同事说:“我以前在餐馆打工,顾客经常点非常多的烙饼。店里的饼大小不一,我习惯在到达顾客饭桌前,把一摞饼按照大小次序摆好——小的在上面,大的在下面。由于我一只手托着盘子,只好用另一只手,一次抓住最上面的几块饼,把它们上下颠倒个个儿,反复几次之后,这摞烙饼就排好序了。我后来想,这实际上是个有趣的排序问题:假设有n块大小不一的烙饼,那最少要翻几次,才能达到最后大小有序的结果呢?”

你能否写出一个程序,对于n块大小不一的烙饼,输出最优化的翻饼过程呢?(参考http://blog.sina.com.cn/s/blog_a2aa00d70101ewuf.html)



问题的关键是,单手每次抓几块饼,全部颠倒。具体参考如图1-1所示

变为

图1-1

每次只能选择最上方的一堆饼,一起翻转,而不能一张张的直接抽出来,然后进行插入,也不能交换任意两块饼。

图1-2演示一下,为了把最大的烙饼摆在最下面,先把最上面的和最大的烙饼之间翻转,这样,最大的烙饼就在最上面了。接着,把所有烙饼翻转,最大的烙饼在最下面了。

变为

变为

图1-2

这是一特殊的例子,经过两次翻转即实现了。两次翻转就可以把最大的烙饼翻转到最下面。因此,最多需要把上面的n-1个烙饼依次翻转两次。那么我们至多需要2(n-1)次翻转就可以把所有烙饼排好序。

单手翻转可以实现,进一步想,怎样减少翻转烙饼的次数呢。

考虑这样一种情况,假如这堆烙饼中有好几个不同的部分相对有序,凭直觉来猜,可以先把小的烙饼进行翻转,让其有序,这样会比每次翻转最大的烙饼要更快。

把两个本来应该相邻的烙饼尽可能地换到一起。这样,等所有烙饼都换到一起之后,实际上就是完成排序了。(从这个医院上讲,每次翻转最大烙饼的方案实质上就是每次把最大的和次大的交换到一起)

在这个基础上,本能的想法是穷举。只要穷举出所有可能的交换方案,那么,我们一定能找到最优的一个。

沿着这个思路,我们自然用动态规划或递归的方法实现,可以从不同的翻转策略开始,比如第一次翻转最小的,然后递归把所有的可能全部翻转一遍,这样,最终肯定是可以找到一个解的。

递归的退出条件是什么呢?第一个退出条件是所有烙饼已经排好序。既然2(n-1)是一个最多的翻转次数,那么在算法中,需要翻转次数多于2(n-1),我们就应该放弃这个方案。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: