Get Min In 0(1) TC
#include <bits/stdc++.h> // Standard headers (iostream, stack, etc.)using namespace std; // Standard namespace
// Class to implement a stack with O(1) getMin() and O(1) space complexityclass SpecialStack { stack<int> st; // The main stack to store elements (some might be modified) int minE; // Stores the current minimum element in the stack
public: // Pushes an element 'data' onto the stack void push(int data) { // Case 1: Stack is empty if(st.empty()) { st.push(data); // Push data directly minE = data; // First element is also the first minimum } // Case 2: Stack is not empty else { // If current data is smaller than or equal to current minimum (new minimum found) if(data < minE) { // Push a modified value to stack to encode previous minimum // Modified value = (2 * new_min - old_min) st.push(2 * data - minE); minE = data; // Update minE to the new minimum } // If current data is greater than current minimum (not a new minimum) else { st.push(data); // Push data directly } } }
// Pops an element from the stack int pop() { // Check for underflow if(st.empty()) { return -1; // Indicate error/empty stack } else { int curr = st.top(); // Get the element from top of stack st.pop(); // Remove it from stack
// If the popped element is greater than current minE // it means it was a normal element, and minE is still correct if(curr > minE) { return curr; // Return the popped element directly } // If the popped element is less than or equal to current minE // it means curr is a modified value (2*new_min - old_min) // and minE was the actual value being popped else { int prevMin = minE; // Store the current minE (which is the actual value being popped) // Restore the previous minimum using the formula: old_min = 2 * current_min - modified_value minE = 2 * minE - curr; return prevMin; // Return the actual value that was popped } } }
// Returns the top element of the stack int top() { if(st.empty()) { return -1; // Indicate empty stack } else { // If stack's top is greater than minE, it's a regular element // Otherwise, it's a modified value, and minE holds the actual top return (st.top() > minE) ? st.top() : minE; } }
// Checks if the stack is empty bool isEmpty() { return st.empty(); }
// Returns the current minimum element in the stack int getMin() { // If stack is empty, there is no minimum return (st.empty()) ? -1 : minE; }};
int main() { // Example Usage: SpecialStack s; s.push(10); // Stack: [10], minE: 10 cout << "Push 10. Top: " << s.top() << ", Min: " << s.getMin() << endl; // Top: 10, Min: 10
s.push(8); // Stack: [10, (2*8-10)=6], minE: 8 cout << "Push 8. Top: " << s.top() << ", Min: " << s.getMin() << endl; // Top: 8, Min: 8
s.push(12); // Stack: [10, 6, 12], minE: 8 cout << "Push 12. Top: " << s.top() << ", Min: " << s.getMin() << endl; // Top: 12, Min: 8
s.push(5); // Stack: [10, 6, 12, (2*5-8)=2], minE: 5 cout << "Push 5. Top: " << s.top() << ", Min: " << s.getMin() << endl; // Top: 5, Min: 5
cout << "Pop: " << s.pop() << endl; // Popped: 5. Stack: [10, 6, 12], minE: 8 (recovers old min) cout << "Top: " << s.top() << ", Min: " << s.getMin() << endl; // Top: 12, Min: 8
cout << "Pop: " << s.pop() << endl; // Popped: 12. Stack: [10, 6], minE: 8 cout << "Top: " << s.top() << ", Min: " << s.getMin() << endl; // Top: 8, Min: 8
cout << "Pop: " << s.pop() << endl; // Popped: 8. Stack: [10], minE: 10 (recovers old min) cout << "Top: " << s.top() << ", Min: " << s.getMin() << endl; // Top: 10, Min: 10
cout << "Pop: " << s.pop() << endl; // Popped: 10. Stack: [], minE: 10 (or -1, effectively) cout << "Top: " << s.top() << ", Min: " << s.getMin() << endl; // Top: -1, Min: -1 (or last set minE)
cout << "Pop (empty): " << s.pop() << endl; // Popped: -1 (empty)
return 0;}Problem
- Design a stack that supports
push,pop,top,isEmpty, andgetMinoperations, all in O(1) time complexity. - Crucially, the
getMinoperation must also work in O(1) space complexity, meaning no auxiliary stack for minimums.
Core Idea: Encoding Previous Minimum
minEVariable: A single integer variableminEalways stores the current minimum element present in the stack.- Modification During Push (When New Minimum Arrives):
- If
data(the element to be pushed) is less thanminE:- We can’t push
datadirectly, because whendatais popped later, we won’t know what the previous minimum was. - Instead, push a
modified_value = (2 * data - minE)onto the stack. - Then, update
minE = data(asdatais the new minimum).
- We can’t push
- If
datais greater than or equal tominE, simplypush(data)onto the stack.minEremains unchanged.
- If
- Modification During Pop (When Current Minimum is Popped):
- If
curr(the element popped from the stack) is greater thanminE:- It means
currwas a regular element, not a modified one. Just returncurr.
- It means
- If
curris less than or equal tominE:- This implies
currwas amodified_valuethat replaced an oldminE. - The actual value being popped is the current
minE. Store this in a temporary variable (prevMin). - The new
minE(the one that was present beforeprevMinbecame the minimum) needs to be recovered. - Use the formula:
new_minE = (2 * minE - curr). (Derived fromcurr = 2 * new_minE - old_minE). - Update
minEtonew_minE. - Return
prevMin(the actual value popped).
- This implies
- If
Explanation of 2*data - minE trick:
- When
datais the new minimum, we store2*data - minE_old. - Let
val_to_push = 2*data - minE_old. - When we
popval_to_push, andval_to_push <= minE_current(whereminE_currentisdata):- The actual value being removed is
minE_current. - The previous minimum was
minE_old. - From
val_to_push = 2*minE_current - minE_old, we can deriveminE_old = 2*minE_current - val_to_push. This is how we restoreminE.
- The actual value being removed is
Operations Summary
push(data):- If
st.empty():st.push(data),minE = data. - Else if
data < minE:st.push(2*data - minE),minE = data. - Else:
st.push(data).
- If
pop():- If
st.empty(): return -1. curr = st.top(),st.pop().- If
curr > minE: returncurr. - Else (
curr <= minE):prevMin = minE,minE = 2*minE - curr, returnprevMin.
- If
top():- If
st.empty(): return -1. - If
st.top() > minE: returnst.top(). - Else (
st.top() <= minE): returnminE(asst.top()is a modified value, andminEholds the actual top element).
- If
getMin(): ReturnminE.isEmpty(): Returnst.empty().