《编程之美——微软技术面试心得》一摞烙饼的排序初体验

《编程之美》读书笔记:1.3 一摞烙饼的排序

问题:

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

你能否写出一个程序,对于n块大小不一的烙饼,输出最优化的翻饼过程呢?


初步分析:

1、使用动态规划来解决,然而不能很快找出状态转移方程,暂时放弃
2、从上到下,从上往下确定当前序列的有序程度(升序、降序),当遇到违背有序的程度的元素的时候,
判断该元素是否在这个有序序列区间范围,
1)若在这个有序序列区间范围,则将该违背有序元素和有序序列一起翻转
2)若不在这个有序序列范围,则将违背有序元素上面的有序序列进行翻转
3)当该元素与序列边界元素相同,则判断该元素下一个元素以确定序列类型
举例子:
输入样例:
5 2 3 7 1
样例分析:
从上往下分析5->2当前序列是降序的,边界范围是[5,2],当遇到3的时候,发现违背当前有序类型(降序),并且3在这个有序序列中,所以翻转这个有序序列和这个元素,得出
3 2 5 7 1
从头再次判断该序列,评估该序列有序类型3->2(降序),边界范围是[3,2],当遇到5的时候,发现违背当前有序类型(降序),因为5不在这个有序序列,所以将违背有序元素上面的有序序列进行翻转,得出
2 3 5 7 1
从头再次判断该序列,评估该序列有序类型3->7(升序),边界范围[3,7],当遇到1的时候,发现违背当前有序类型(降序)因为1不在这个有序序列,所以将违背有序元素上面的有序序列进行翻转,得出
7 5 3 2 1
从头再次判断该序列,评估该序列有序类型7->1(降序),但是题目要求序列最终有序类型是升序,所以整个序列再次翻转一次,得出
1 2 3 5 7
/*
把一摞饼按照大小次序摆好——从小到大,小在上,大在下
只能用一只手,一次抓住最上面的几块饼,把他们上下颠倒个个儿,
反复几次之后,排好序
假设有n块大小不一的烙饼,最少翻转几次,才能达到大小有序的结果?
*/
#define  _CRT_SECURE_NO_WARNINGS 
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
void printData(int val)
{
	cout << val << " ";
}
void init_bin(vector<int> &v)
{
	int n;//需要排序的饼的数目
	cin >> n;
	for (int i = 0; i < n; i++)
	{
		int a;
		cin >> a;
		v.push_back(a);
	}
}

void sort_bin(vector<int> &v)
{
	while (1)
	{
		bool flag ;//排序标记
		int pStart = 1;//默认开始遍历的下标为2
		if (v[1] == v[0])
		{
			while (v[pStart] == v[pStart - 1] && pStart < v.size())pStart++;//若元素相同,则判断下一个
		}
		flag = v[pStart]>v[pStart - 1];//确定当前排序类型(升序、降序)
		bool next = flag;
		for (int i = pStart + 1; i < v.size(); i++)
		{
 			while (v[i] == v[i - 1] && i < v.size())i++;
			next = v[i]>v[i - 1];//确定当前元素与上一个比较后是升序还是降序
			if (next==flag)//与原本序列违背
				continue;
 			auto _Start = &v[0];
			int *_End;
			//while (v[i] == v[0] && i < v.size())i++;
			if (flag ==v[i] > v[0]&& v[i] != v[0])
			{
				_End = &v[i];
			}
			else
			{
				_End = &v[i - 1];
			}
			reverse(_Start, _End+1);
			for_each(v.begin(), v.end(), printData); cout << endl;
			break;
		}//for
		if (next==flag&&flag)break;
		else if (next == flag&&flag == false)
		{
			reverse(v.begin(), v.end());
			for_each(v.begin(), v.end(), printData); cout << endl;
		}
	}//while
}

int main(void)
{
	vector<int> v;
	init_bin(v);
	
	sort_bin(v);
	cout << endl;
	system("pause");
	return 0;
}

存在问题:
只分析上方有序程度,但是该序列其他部分有序程度并没有分析
比如
10
3 2 1 6 5 4 9 8 7 0
这个样例就存在着部分区域有序的现象,[3,1] [6,4] [9,7][0],而这种情况的话,上述程序在6的时候已经分析错误了,要修改,请大神指教。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值