THU数据结构编程作业一:隧道(Tunel)
来源:互联网 发布:手机卫士源码 编辑:程序博客网 时间:2024/06/13 08:04
本题主要解决的问题:
常数时间复杂度范围内获得栈的最大值;
用两个栈模拟一个队列。
细节问题:scanf 和 getchar 获取输入的问题。
问题描述
现有一条单向单车道隧道,每一辆车从隧道的一端驶入,另一端驶出,不允许超车。该隧道对车辆的高度有一定限制,在任意时刻,管理员希望知道此时隧道中最高车辆的高度是多少。
现在请你维护这条隧道的车辆进出记录,并支持查询最高车辆的功能
输入
第一行仅含一个整数,即高度查询和车辆出入操作的总次数n
以下n行,依次这n次操作。各行的格式为以下几种之一:
1. E x //有一辆高度为x的车进入隧道(x为整数)2. D //有一辆车离开隧道3. M //查询此时隧道中车辆的最大高度
输出
若D和M操作共计m次,则输出m行
对于每次D操作,输出离开隧道车辆的高度
对于每次M操作,输出所查询到的最大高度
样例
Input
9E 5E 6ME 2MDMDM
Output
665662
限制
0 ≤ n ≤ 2,000,000
0 ≤ x ≤ 2^31 - 1
保证车辆的进出序列是合法的
时间:2 sec
空间:256 MB
提示
如何由多个栈来模拟一个队列?可参考第四章末尾的某习题。
如何实现一个能够高效获取最大值的栈?
如何实现一个可以高效获取最大值的队列?
可参考第04章XA节的讲义以及《习题解析》的[10-19]题、[10-20]题.
先上上源代码:
#include<cstdio>#include<cstdlib>using namespace std;//fast ioconst size_t sz = 1 << 20;struct fastio{ char inbuf[sz]; char outbuf[sz]; fastio(){ setvbuf(stdin, inbuf, _IOFBF, sz); setvbuf(stdout, outbuf, _IOFBF, sz); }}io;//maximum tunel lengthconst size_t max_sz = 2000010;//simulate a queue by two stackslong stack_push[max_sz];long stack_pop[max_sz];//simulate two pointers for pop and push operationslong stack_push_pointer(0),stack_pop_pointer(0);//store max value for two stackslong stack_push_max(0), stack_pop_max(0);//push elements into enqueue stackvoid stack_push_push(long e){ //store the difference of element and maxvalue stack_push[++stack_push_pointer] = e - stack_push_max; //if the stored elements is negative, the max value should be the new element if(stack_push_max < e) stack_push_max = e;}//pop elements to the dequeuing stack to be dequeuedlong stack_push_pop(){ if(stack_push_pointer < 1){ printf("STACK_PUSH POP ERROR!\n"); return 0; } long e; //if the poping element is not negative, the top element is the maxvalue //then the maxvalue should be changed. if(stack_push[stack_push_pointer] >= 0){ e = stack_push_max; stack_push_max = stack_push_max - stack_push[stack_push_pointer]; }else e = stack_push_max + stack_push[stack_push_pointer];//recover the oroginal value --stack_push_pointer; return e;}//push elements into dequeuing stack and record the max valuevoid stack_pop_push(long e){ stack_pop[++stack_pop_pointer] = e - stack_pop_max; if(stack_pop_max < e) stack_pop_max = e;}//dequeue from the dequeuing stack long stack_pop_pop(){ if(stack_pop_pointer < 1){ printf("STACK_POP POP ERROR!\n"); return 0; } long e; if(stack_pop[stack_pop_pointer] >= 0){ e = stack_pop_max; stack_pop_max = stack_pop_max - stack_pop[stack_pop_pointer]; }else e = stack_pop_max + stack_pop[stack_pop_pointer]; --stack_pop_pointer; return e;}int main(){ //redirect IO#ifndef _OJ_ freopen("input.txt", "r", stdin); freopen("output.txt", "w", stdout);#endif long op_size;//operation times; scanf("%ld", &op_size); getchar(); char com_char;//command character long com_int;//command parameter long temp; while(op_size-- > 0){ do{ com_char = getchar(); }while(com_char != 'E' && com_char != 'D' && com_char != 'M');// scanf("%c", &com_char);//get command character// if(com_char == 'E')//if enqueue, read the height of vehical// scanf("%ld", &com_int);// getchar(); switch(com_char){ case('E'): scanf("%ld", &com_int); stack_push_push(com_int); break; case('D'): if(stack_pop_pointer == 0){ for(long i = stack_push_pointer; i > 0; --i) stack_pop_push(stack_push_pop()); } temp = stack_pop_pop(); printf("%ld\n", temp); break; case('M'): temp = stack_push_max >= stack_pop_max ? stack_push_max : stack_pop_max; printf("%ld\n", temp); break; default: break; }; } return 0;}
首先需要说明的是上面程序的设计并不是很好,完全没有用到类的设计,以及用了很多全局变量,这只是出于提高程序运行速度考虑,整个算法应该是没有问题的。
本题主要有两个问题:
求栈的最大值问题,
如何用两个栈模拟一个队列。
求栈最大值问题
问题描述
一个整数栈stack,具有push和pop操作,其时间空间复杂度皆为O(1)。
设计算法max操作,求栈中的最大值,该操作的时间空间复杂度也要求为O(1)。
可以修改栈的存储方式,push,pop的操作,但是要保证O(1)的时间空间复杂度。
算法描述
变量Max保存当前最大元素值,初始值为最小整数m。
1. 当push入栈时,将(当前元素-Max)存入栈中, 若当前元素小于Max,栈中元素为负数; 若当前元素大于等于Max,栈中元素为非负数,将Max替换为当前元素。
2. 当pop出栈时, 若栈中元素为负数,则将(栈中元素+Max)弹出栈; 若栈中元素为非负数,则将Max弹出栈,并将Max替换为(Max-栈中元素)。
3. Max即为当前栈中最大元素值。主要思路是将最大值以某种方式在原有栈中标记出来,从而减少空间使用。可以用正负数来区分普通元素和最大值元素:
普通元素使用负数存储(元素-Max);
最大值元素使用非负数存储(New Max - Old Max);
这样便可在栈中区分普通元素和最大值元素,并可通过Max恢复Old Max。
以上算法分析内容源自: 面试题——栈的最大值问题
假设入栈序列为:3,1,2,5,7,4,6,假设原栈顶元素为 0,原Max = 0:
上图,元素3-Max,即 3-0 = 3,首先入栈,因为 3>0,所以Max变成3,;随后,1 -Max,即1-3=-2,压入栈,,-2<3, 所以Max不变依然为3,元素2 同理。
上图,元素5,将5-Max,即5-3=2,压入栈,因为2>0,所以同时将Max变成5;
上图,元素7,将7-Max,即7-5=2压入栈,同时将Max变成7;
上图元素4,6同理入栈。
上图,对于元素6,因为栈顶元素小于0,所以出栈是Max不变,并将出栈元素恢复为原来的值,-1+Max,即-1+7 =6.出栈,同理元素4 出栈。
上图,元素7,因为栈顶元素大于0,所以判断当前栈顶元素为栈的最大值Max,即为7,当栈顶弹出后Max应该改变,即Max = Max - 2= 7 - 2 =5;
上图,元素5,同理,因为栈顶元素大于0,所以判断当前应该弹出的栈顶元素等于Max,即 5,同时Max= Max - 2=5-2=3;
上图,再次弹出栈顶时因为栈顶元素小于0,所以Max不变,弹出当前栈顶的值加上Max,即为2,同理弹出元素 1。
最终全栈只剩下元素3,Max = 3。
用两个栈模拟一个队列
原理如下图所示:
本程序用两个数组来模拟两个栈,然后将这两个栈模拟成一个队列。push操作是将元素压入stack_push中,在执行pop操作时首先判断stack_pop是否为空,如果为空则将stack_push中的所有元素依次弹出并压入到stack_pop栈中以待pop操作。同时,对于这两个栈在各自的pop和push操作时都分别记录自己的Max(stack_push_max 和 stack_pop_max),而两者的最大值即为整个队列的最大值。
以上就解决了程序的主要两个问题。
另外在调试时遇到了输入和输出的问题,即在读取命令是注释的那部分程序是最初的读入代码后来在OJ上调试总是有三个过不了。调试了很久,代码也反复检查了很久,最后将那部分读命令的程序改了以后就100%通过了。scanf 和getchar 获得输入而引发的问题貌似常常会出现。
- THU数据结构编程作业一:隧道(Tunel)
- THU数据结构编程作业一:查询范围(Range)
- THU数据结构编程作业一:祖玛(Zuma)
- THU数据结构编程作业一:列车调度(Train)
- THU数据结构编程作业一:真二叉树重构(Proper Rebuild)
- Tsinghua OJ:隧道(Tunel)
- 编程作业(一)
- THU组合数学第二周作业
- Tsinghua OJ 数据结构编程作业:祖玛(Zuma)
- [数据结构]第五次作业:huffman编码及其译码(一)
- 校园导航——数据结构作业(一)
- 第一次作业(数据结构)
- 【数据结构】邓玉欣的编程作业indexing
- 浙江大学数据结构第一周编程作业【Java】
- 数据结构与算法B作业一,概论
- Java入门编程(作业)实现总结(一)
- Java入门编程(作业)Time3实现总结(一)
- 机器学习:SVM作业编程实现(一)
- IE6、IE7、IE8、Firefox兼容性CSS HACK代码+示例
- IntelliJ IDEA 快捷键和设置
- 如何查找老公已删除的微信聊天记录
- Eclipse工程转换为Android Studio工程
- 谈谈科创
- THU数据结构编程作业一:隧道(Tunel)
- 使其适应相应的iphone大小展示
- Android Service完全解析
- POJ-2163
- 有用的链接
- C++:函数
- phalapi-进阶篇1(Api,Domain,和Model)
- ALM
- susan角点检测算法