程序员面试金典: 9.3栈与队列 3.2设计一个栈,除pop与push方法,支持返回栈最小元素min方法,时间复杂度均为O(1)

#include <iostream>
#include <stdio.h>
#include <stack>
#include <string>

using namespace std;

/*
问题:请设计一个栈,除pop与push方法,还支持min方法,可返回栈元素中的最小值。
      push,pop,min三个方法的时间复杂度为O(1)
分析:能否再普通栈的基础上维持一个最小元素的值,获取最小值时就返回它。
       关键是如何找到最小值下面的次最小值?
	   寻找此最小值的过程可能需要把所有元素拿出来比较。
	   除非设置一个排好序的栈。
书上解法:
牛叉。直接用另一个栈来记录最小值。压入时,除了栈本身压入元素外,如果当前元素<=最小值,那么压入第二个栈中。【防止后面当前元素=最小值时弹出该元素后,后续就没有最小值】
      弹出时,如果当前元素等于最小值时,第二个栈也弹出元素。
	  求最小值时,就返回当前栈的栈顶元素。
我之所以未能做出:就是把思维局限在只有一个栈上,求最小值需要遍历该栈。而正确的做法直接用另外一个栈保存最小值,里面记录了最小值,就不需要遍历操作。
输入:
4(输入栈的元素个数)
5 6 3 7
1(指令个数)
pop 2(pop次数2次)
输出:
5

关键:
1 采用栈中保存另一个栈来记录最小值。在每一次插入元素时,当前元素<=最小值时,就将最小值压入第二个栈中。
  弹出时,当前元素=最小值时,第二个栈也弹出最小值
*/

class MinStack : public stack<int>
{
public:
	MinStack(){}
	void push(int value)
	{
		stack<int>::push(value);
		//如果当前元素的值 <= 最小值,就压入最小元素,这里等于时要压入,否则后续当前元素=最小值 弹出元素后会导致下次遇到同样情况,无法弹出最小元素
		if( value <= min() )
		{
			minStack.push(value);
		}
	}
	void pop()
	{
		int value = stack<int>::top();
		stack<int>::pop();
		//如果当前值就是最小值,弹出最小栈中对应最小值
		if(value == min())
		{
			minStack.pop();
		}
	}
	int min()
	{
		if( minStack.empty() )
		{
			return INT_MAX;
		}
		else
		{
			return minStack.top();
		}
	}
private:
	stack<int> minStack;
};

int main(int argc, char* argv[])
{
	int n , commandNum;
	while(cin >> n)
	{
		int* pArr = new int[n];
		MinStack minStack;
		for(int i = 0 ; i < n ; i++)
		{
			cin >> *(pArr + i) ;
			minStack.push( *(pArr + i) );
		}
		//获取命令
		cin >> commandNum;
		string command;
		int value;
		for(int j = 0 ; j < commandNum ; j++)
		{
			cin >> command >> value;
			if(command == "pop")
			{
				for(int k = 0 ; k < value ; k++)
				{
					minStack.pop();
				}
			}
			else if(command == "push")
			{
				minStack.push(value);
			}
		}
		//输出最小元素
		cout << minStack.min() << endl;
		delete[] pArr;
	}
	getchar();
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值