Implement a stack that is able to return the maximum of the stack at any moment. All operations must be O(1), or amortized O(1) on the push operation.
The Idea:
We maintain a secondary stack, that which we will call MaxStack. It is a special kind of stack, so it should have very similar methods, with a few exceptions.
We will encapsulate a regular stack, that will be used to maintain the MaxStack ordinary operators like push, pop, top.
MaxStack will interface with another stack we will call max_s that overwrites a few operators.
push will add the new integer to max stack iff it exceeds the current size of its current max. This has the effect of maintaining a history of the max elements pushed in.
So when we pop we will naturally obtain the previous max element that will always be inline with the ordinary stack, since we pop from both containers.
class Stack
{
public:
Stack(const size_t n) {
s.reserve(n);
iter = 0;
}
Stack() { iter = 0; }
void reserve(const size_t n) { s.reserve(n); }
virtual bool empty() { return iter == 0; }
int top()
{
if (!empty()) return (s.at(iter - 1));
else throw "empty";
}
virtual void push(const int n)
{
if (iter >= s.size()) {
s.push_back(n);
iter++;
}
else s.at(iter++) = n;
}
virtual void pop()
{
if (!empty()) iter--;
else throw "empty";
}
private:
vector<int> s;
int iter;
};
class MaxStack : public Stack
{
public:
MaxStack(const size_t size) {
Stack::reserve(size);
max_s.reserve(size);
iter = 0;
}
void push(const int n)
{
Stack::push(n);
if (empty()) max_s.push(n);
else if (!empty() && n < max_s.top()) {
max_s.push(max_s.top());
}
else max_s.push(n);
iter++;
}
void pop()
{
if (!empty()) {
Stack::pop();
max_s.pop();
iter--;
}
else throw "empty";
}
int max()
{
if (!empty())
return max_s.top();
else throw "empty";
}
bool empty() { return iter == 0; }
private:
Stack max_s;
int iter;
};
int main()
{
cout << "ascending" << endl;
MaxStack s(30);
vector<int> elements = {1,2,3,4,5,6,7,8,9,9,9};
for (int i : elements) {
s.push(i);
cout << s.max() << " ";
}
cout << "\n\n";
try
{
while (!s.empty()) {
s.pop();
cout << s.max() << " ";
}
}
catch (const char* msg) {
cerr << msg << endl;
}
cout << "\n\n\n";
cout << "descending" << endl;
MaxStack s2(30);
vector<int> elements2 = { 9,9,9,8,7,6,5,4,3,2,1 };
for (int i : elements2) {
s2.push(i);
cout << s2.max() << " ";
}
cout << "\n\n";
try
{
while (!s2.empty()) {
s2.pop();
cout << s2.max() << " ";
}
}
catch (const char* msg) {
cerr << msg << endl;
}
}