您的位置:首页 > 编程语言

1.3 翻烙饼问题

2015-08-09 19:46 260 查看

1. 前言

本文的一些图片, 资料 截取自编程之美

2. 问题描述



3. 问题分析



书上提供了两种思路

一种 : 就是每一次用两次交换将当前最大的烙饼翻到最下面

另一种 : 是递归穷举, 上界为上面的分析出的(2 * (n - 1))

但是, 我这里并没有实现递归穷举的算法, 我这里实现的另一种思路是 : 将相邻的有序的数字(们), 一起翻转, 但是从效果上来看,貌似这个思路, 和第一个思路相差不大呀

4. 代码

/**
* file name : Test28SortPie.java
* created at : 10:58:38 AM May 10, 2015
* created by 970655147
*/

package com.hx.test02;

public class Test28SortPie {

// 翻烙饼问题
public static void main(String []args) {
long start = System.currentTimeMillis();

//      int pie[] = {0, 4, 5, 2, 1, 6, 7, 3, 9, 8, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10 };
int pie[] = {40, 67, 99, 31, 9, 84, 89, 58, 74, 13, 33, 2, 92, 85, 24, 95, 52, 93, 22, 12, 45, 21, 96, 39, 10, 68, 46, 90, 23, 64, 51, 78, 100, 32, 87, 41, 71, 82, 37, 6, 18, 80, 59, 77, 28, 42, 73, 72, 98, 91, 50, 60, 53, 83, 86, 63, 70, 88, 17, 11, 69, 14, 19, 4, 1, 16, 29, 30, 34, 94, 38, 76, 55, 36, 5, 66, 75, 20, 44, 35, 56, 8, 25, 7, 49, 26, 61, 47, 15, 27, 54, 97, 48, 43, 65, 79, 3, 81, 62, 57 };

print(pie);

//      sortPie(pie);
sortPie02(pie);

print(pie);

long spent = System.currentTimeMillis() - start;
System.out.println("spent : " + spent + " ms");

}

// 每次将最大的烙饼先翻到最上面  在翻到"最下面"
// 将当前最大的元素 翻转到最上面, 然后在反转到最下面
public static void sortPie(int[] pie) {
int cnt = 0;
int step = pie.length - 1;

for(; step > 0; step --) {
int index = findMaxValueIndex(pie, step);

if(index != step) {
if(index != 0) {
revert(pie, 0, index);
cnt ++;
}
revert(pie, 0, step);
cnt ++;
}
}

System.out.println("reverted : " + cnt + " times...");
}

//  // 注意 : pie最好按照其大小编号[比如最小的为1号, 次小的为2号, ...], 因为这里判断是否是小于当前最大值的依据是前一个数或者后一个数是否是(当前的数-1)
//  // 每次将最大的烙饼先翻到最上面  在翻到"最下面"
//  // 不过如果存在有序的序列  将该序列的烙饼翻到合适的地方   详见代码
public static void sortPie02(int[] pie) {
int cnt = 0;
int step = pie.length - 1;

while(step > 0) {
//          print(pie);

boolean existsSeq = false;
int maxIdx = findMaxValueIndex(pie, step);
int idxBefore = -1, idxAfter = -1;
int endOfSortedIdx = -1;
for(idxBefore=maxIdx; (idxBefore>0) && ((pie[idxBefore-1]+1) == pie[maxIdx]); idxBefore -- ) ;
for(idxAfter=maxIdx; (idxAfter<step) && ((pie[idxAfter+1]+1) == pie[maxIdx]); idxAfter ++ )     ;
if((idxAfter - maxIdx) < (maxIdx - idxBefore) ) {
endOfSortedIdx = idxBefore;
} else {
endOfSortedIdx = idxAfter;
}

if(endOfSortedIdx == idxBefore) {
// ..., idxBefore, ..., maxIdx, ...
// 有序的共有((maxIdx - endOfSortedIdx) + 1) 个元素
if(maxIdx != step) {
revert(pie, 0, maxIdx);
revert(pie, 0, step);
cnt += 2;
}
step = step - ((maxIdx - endOfSortedIdx) + 1);
} else {
// ..., maxIdx, ..., idxAfter, ...
// 有序的共有((idxAfter - maxIdx) + 1) 个元素
if(maxIdx == 0) {
revert(pie, 0, endOfSortedIdx);
cnt ++;
} else {
revert(pie, 0, endOfSortedIdx);
revert(pie, 0, (idxAfter-maxIdx));
cnt += 2;
}
revert(pie, 0, step);
cnt ++;
step = step - ((endOfSortedIdx - maxIdx) + 1);
}
}

System.out.println("reverted : " + cnt + " times...");
}

public static void revert(int[] pie, int start, int end) {
System.out.println(start + " -> " + end);

// 将start -> end的数据翻转
for(int i=start, j=end; i<j; i++, j--) {
int t = pie[i];
pie[i] = pie[j];
pie[j] = t;
}
}

// 找到数组中最大的值
public static int findMaxValueIndex(int[] pie) {
int index = 0;
int maxVal = Integer.MIN_VALUE;

for(int i=0; i<pie.length; i++) {
if(pie[i] > maxVal) {
index = i;
maxVal = pie[i];
}
}

return index;
}

// 找到数组中前depth个数据中最大的元素的索引
public static int findMaxValueIndex(int[] pie, int depth) {
int index = 0;
int maxVal = Integer.MIN_VALUE;

for(int i=0; i<=depth; i++) {
if(pie[i] > maxVal) {
index = i;
maxVal = pie[i];
}
}

return index;
}

// 找到数组中小于max的值的最大的值的索引
public static int findMaxValueIndexWithInMax(int[] pie, int max) {
int index = 0;
int maxVal = Integer.MIN_VALUE;

for(int i=0; i<pie.length; i++) {
if(pie[i] > maxVal && pie[i] < max) {
index = i;
maxVal = pie[i];
}
}

return index;
}

public static void print(int[] arr) {
StringBuilder sb = new StringBuilder(arr.length * 10);
//      for(int i=0; i<arr.length; i++) {
//          sb.append(i + " ");
//      }
//      sb.append("\r\n");
for(int i=0; i<arr.length; i++) {
sb.append(arr[i] + " ");
}

System.out.println(sb.toString());
}

}


5. 运行结果





6. 总结

常规的思路, 不是那么难想出来, 但是要想找出一种非常好的算法,就太难了

注 : 因为作者的水平有限,必然可能出现一些bug, 所以请大家指出!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  编程之美