Skip to content

Latest commit

 

History

History
107 lines (78 loc) · 3.06 KB

Monotonic-Stack-&-Queue.md

File metadata and controls

107 lines (78 loc) · 3.06 KB

Monotonic Stack & Queue

Monotonic Stack

Definition

A monotonic stack is a stack with its elements ordered monotonically. Specificly, it maintains the monotonicity by popping elements when a new element e is pushed into the stack.

Usage

Monotonic stacks are best suited for problems that requires finding the next/previous greater/smaller element in a list of elements. You just iterate through the list and push elements into the stack. The top element in the stack right before the new element is actually pushed into the stack is the next/previous greater/smaller element of the pushed element. The complexity of doing so for each element in the list is linear.

  • For greater problems, use a monotonically increasing stack (from top to bottom).
  • For smaller problems, use a monotonically decreasing stack (from top to bottom).
  • For next problems, backwardly iterate through the list and push elements into the stack.
  • For previous problems, forwardly iterate through the list.
  • For problems with a circular list, iterate through the list twice.

Implementation

Default: nonstrictly monotonically decreasing stack.

template <typename T, typename Compare = std::less<T>>
class MonotonicStack {
public:
    MonotonicStack() { }

    MonotonicStack(const Compare& compare) : cmp(compare) { }

    bool empty() {
        return s.empty();
    }

    T top() {
        return s.top();
    }

    void push(T e) {
        while (!s.empty() && cmp(e, s.top()) {
            s.pop();
        }
        s.push(e);
    }

    void pop() {
        s.pop();
    }
private:
    stack<T> s;
    Compare cmp;
};

Problems

Monotonic Queue

Definition

A monotonic queue is a queue with its elements ordered monotonically. Specificly, it maintains the monotonicity by dequeuing elements when a new element e is enqueued, while a priority queue maintains the monotonicity by sorting/heapifying when a new element e is enqueued.

Usage

Implementation

Default: nonstrictly monotonically increasing queue.

template <typename T, typename Compare = std::less<T>>
class MonotonicQueue {
public:
    MonotonicQueue() { }

    MonotonicQueue(const Compare& compare) : cmp(compare) { }

    bool empty() {
        return q.empty();
    }

    T front() {
        return q.front();
    }

    void push(T e) {
        while (!q.empty() && cmp(e, s.back()) {
            q.pop_back();
        }
        q.push_back(e);
    }

    void pop(T e) {
        if (!q.empty() && q.front() == e)
            q.pop_front();
    }
private:
    deque<T> q;
    Compare cmp;
};

Problems