剑指Offer - 面试题30:包含min函数的栈

Posted 林夕07

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了剑指Offer - 面试题30:包含min函数的栈相关的知识,希望对你有一定的参考价值。

题目

实现一个特殊的栈,在实现栈的基本功能的基础上,再实现返回栈中最小元素的操作。

本题在《程序员代码面试指南-左程云》 第一章 栈和队列 中也有

要求

  1. pop、push、getMin操作的时间复杂度都是O(1)
  2. 设计的栈类型可以使用线程的栈结构

分析

双栈法

我们可以用一个stackmin(辅助栈)栈用来存储每次出栈stackdata(数据栈)或者入栈之后栈中的最小值。

  1. 入栈。将数据与stackmin的栈顶元素对比,若发现,新来的值小于等于栈顶值,就将该数据也放在stackmin中。否则不添加。只放在stackData中。特殊情况当stackmin为空时,直接将数据放入stackmin中。
  2. 出栈。如果发现将要出栈的值等于stackmin栈顶值,就stackmin连带出栈。
    C++
#include<iostream>
#include<stack>

using namespace std;


template <typename T> class MyStack
{
public:

	MyStack();
	~MyStack();

	void push(T newNum);
	void pop();
	T top();
	T getmin();


private:
	stack<int> stackData;
	stack<int> stackMin;
};

template <typename T> MyStack<T>::MyStack()
{
}

template <typename T> MyStack<T>::~MyStack()
{
}

template <typename T> void MyStack<T>::push(T newNum)
{
	if (stackMin.empty() == true || newNum <= stackMin.top())
	{
		stackMin.push(newNum);
	}
	stackData.push(newNum);
}

template <typename T> void MyStack<T>::pop()
{
	if (stackData.top() == stackMin.top())
	{
		stackMin.pop();
	}
	stackData.pop();
}

template <typename T> T MyStack<T>::top()
{
	return stackData.top();
}

template <typename T> T MyStack<T>::getmin()
{
	return stackMin.top();
}


int main()
{
	MyStack<int> s;
	s.push(3);
	cout << "入栈。栈中有数据3:最小值为:" << s.getmin() << endl;
	s.push(2);
	cout << "入栈。栈中有数据3、2:最小值为:" << s.getmin() << endl;
	s.push(1);
	cout << "入栈。栈中有数据3、2、1:最小值为:" << s.getmin() << endl;
	s.push(5);
	cout << "入栈。栈中有数据3、2、1、5:最小值为:" << s.getmin() << endl;
	s.push(1);
	cout << "入栈。栈中有数据3、2、1、5、1:最小值为:" << s.getmin() << endl;
	s.pop();
	cout << "出栈。栈中有数据3、2、1、5:最小值为:" << s.getmin() << endl;
	s.pop();
	cout << "出栈。栈中有数据3、2、1:最小值为:" << s.getmin() << endl;
	s.pop();
	cout << "出栈。栈中有数据3、2:最小值为:" << s.getmin() << endl;
	s.pop();
	cout << "出栈。栈中有数据3:最小值为:" << s.getmin() << endl;

	return 0;
}

在这里插入图片描述

优化辅助栈

假如我们用一个变量min保存最小值,每次入栈进行比较,然后更新。但是有一个缺陷,一旦删除了最小值,就找不到了新的最小值。所以我们在发现新的最小值要入栈时提前将之前的最小值入栈。当我们删除的值和保存的min值相同时。再从栈中取出栈顶元素(我们事先放好之前的最小值)。给到min中。
在这里插入图片描述
C++

#include<iostream>
#include<stack>

using namespace std;


template <typename T> class MyStack
{
public:

	MyStack();
	~MyStack();

	void push(T newNum);
	void pop();
	T top();
	T getmin();


private:
	stack<int> stackData;
	T stackMin;
};

template <typename T> MyStack<T>::MyStack()
{
}

template <typename T> MyStack<T>::~MyStack()
{
}

template <typename T> void MyStack<T>::push(T newNum)
{
	if (stackData.empty() == true || newNum <= stackData.top())
	{
		stackData.push(stackMin);	//把之前的最小值提前入栈
		stackMin = newNum;			//更新新的最小值
	}
	stackData.push(newNum);
}

template <typename T> void MyStack<T>::pop()
{
	if (stackData.empty() == true)
	{
		exit(EXIT_FAILURE);
	}

	if (stackData.top() == stackMin)//删除的是当前的最小值
	{
		stackData.pop();
		stackMin = stackData.top();	//把事先存入栈中的最小值给到stackmin
		stackData.pop();			//再把该值删除
	}
	else
	{
		stackData.pop();
	}
}

template <typename T> T MyStack<T>::top()
{
	return stackData.top();
}

template <typename T> T MyStack<T>::getmin()
{
	return stackMin;
}


int main()
{
	MyStack<int> s;
	s.push(3);
	cout << "入栈。栈中有数据3:最小值为:" << s.getmin() << endl;
	s.push(2);
	cout << "入栈。栈中有数据3、2:最小值为:" << s.getmin() << endl;
	s.push(1);
	cout << "入栈。栈中有数据3、2、1:最小值为:" << s.getmin() << endl;
	s.push(5);
	cout << "入栈。栈中有数据3、2、1、5:最小值为:" << s.getmin() << endl;
	s.push(1);
	cout << "入栈。栈中有数据3、2、1、5、1:最小值为:" << s.getmin() << endl;
	s.pop();
	cout << "出栈。栈中有数据3、2、1、5:最小值为:" << s.getmin() << endl;
	s.pop();
	cout << "出栈。栈中有数据3、2、1:最小值为:" << s.getmin() << endl;
	s.pop();
	cout << "出栈。栈中有数据3、2:最小值为:" << s.getmin() << endl;
	s.pop();
	cout << "出栈。栈中有数据3:最小值为:" << s.getmin() << endl;

	return 0;
}

在这里插入图片描述

本章完!

以上是关于剑指Offer - 面试题30:包含min函数的栈的主要内容,如果未能解决你的问题,请参考以下文章

剑指Offer - 面试题30:包含min函数的栈

剑指offer:面试题21包含min函数的栈

[剑指offer]面试题21:包含min函数的栈

剑指offer 面试30题

剑指Offer对答如流系列 - 包含min函数的栈

剑指 Offer 30. 包含min函数的栈