1.3 一摞烙饼的排序
一摞烙饼的排序
基本问题
假设有n块大小不一样的烙饼,那么最少要翻动几次,才能达到最终有序的结果。
思路:每次找到最大的然后从将最大的以及最大的上面的反转,这时候最大的在最上面,然后将整个反转,最大的就在最下面了。然后再对除了最下面的n-1个烙饼进行上述的操作,知道全部的烙饼有序。
例如:13524---> 53124--->42135
class Test{
public static void main(String[] args) {
// 一摞烙饼
int[] arr = new int[]{2,3,5,4,1};
reverse(arr,0,arr.length-1);
// flag表示找了几次最大的值,也就是已经将flag个大饼放在的最下面
int flag = 0;
while(flag < arr.length){
// 找到最大的饼所在的位置
int index = 0;
for(int i = 0;i<arr.length - flag;i++){
if(arr[index] < arr[i]) index = i;
}
// 翻转
reverse(arr,0,index);
// 再次反转
reverse(arr,0,arr.length - flag - 1);
flag++;
}
for(int i:arr) System.out.print(i+" ");
System.out.println();
}
// 按照索引进行翻转
public static void reverse(int[] arr,int left,int right){
while(left < right){
int tmp = arr[left];
arr[left] = arr[right];
arr[right] = tmp;
left++;
right--;
}
}
}
还有一个解题方案是穷举方案,每一次都将本应该在一起的两个烙饼放在一起,当反转次数大于上述的方法的反转次数也就是\(2(n-1)\)次的时候,放弃这个算法。
拓展问题
1.有一些服务员会把上面的烙饼放在自己的帽子上,然后继续处理其他烙饼,在这个条件下,我们的算法能有什么改进
我的想法是类似于程序中的空间换时间,找到最大的烙饼之后,将最大的烙饼上面的烙饼放在自己的头上,然后只反转自己手里面的烙饼,翻转完成之后,再将头上的烙饼拿下来重新对n-1个烙饼实施上述操作,直到全部有序。
2.有时候,烙饼一面金黄,一面比较焦,让金黄的一面在上面
很简单,就是在每次将最大的烙饼在最上面的时候,判断金黄的一面是否在上面,如果是直接反转,如果不是,先反转最大的烙饼,然后再反转全部的烙饼即可。
3.有一次,师傅烙了3个饼,一个均是金黄,一个均是焦,一个一面焦一面金黄,如果已经知道最上面是焦,则问这个最上面的饼的反面也是焦的概率是多少?
\[result = \frac{1}{2}
\]
4. 每次反转烙饼的时候,上面的若干个烙饼会被反转,如果我们希望在排序过程中,翻转烙饼的次数最少,结果会是如何呢?
多用几个帽子
5.目前针对这个问题研究出来的结果
翻转所有饼的最大下界是\(\frac{15}{14} * n\)
翻转所有的病的最小上界是\(\frac{5*n + 5}{3}\)
Saying Less Doing More