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
, andgetMin
operations, all in O(1) time complexity. - Crucially, the
getMin
operation must also work in O(1) space complexity, meaning no auxiliary stack for minimums.
Core Idea: Encoding Previous Minimum
minE
Variable: A single integer variableminE
always 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
data
directly, because whendata
is 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
(asdata
is the new minimum).
- We can’t push
- If
data
is greater than or equal tominE
, simplypush(data)
onto the stack.minE
remains unchanged.
- If
- Modification During Pop (When Current Minimum is Popped):
- If
curr
(the element popped from the stack) is greater thanminE
:- It means
curr
was a regular element, not a modified one. Just returncurr
.
- It means
- If
curr
is less than or equal tominE
:- This implies
curr
was amodified_value
that 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 beforeprevMin
became the minimum) needs to be recovered. - Use the formula:
new_minE = (2 * minE - curr)
. (Derived fromcurr = 2 * new_minE - old_minE
). - Update
minE
tonew_minE
. - Return
prevMin
(the actual value popped).
- This implies
- If
Explanation of 2*data - minE
trick:
- When
data
is the new minimum, we store2*data - minE_old
. - Let
val_to_push = 2*data - minE_old
. - When we
pop
val_to_push
, andval_to_push <= minE_current
(whereminE_current
isdata
):- 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, andminE
holds the actual top element).
- If
getMin()
: ReturnminE
.isEmpty()
: Returnst.empty()
.