Design a stack that supports push, pop, top, and retrieving the minimum element in constant time.
push(x) — Push element x onto stack.
pop() — Removes the element on top of the stack.
top() — Get the top element.
getMin() — Retrieve the minimum element in the stack.
Java Solution
To make constant time of getMin(), we need to keep track of the minimum element for each element in the stack. Define an element class that holds element value, min value, and pointer to elements below it.
class Elem{ public int value; public int min; public Elem next; public Elem(int value, int min){ this.value = value; this.min = min; } } public class MinStack { public Elem top; /** initialize your data structure here. */ public MinStack() { } public void push(int x) { if(top == null){ top = new Elem(x, x); }else{ Elem e = new Elem(x, Math.min(x,top.min)); e.next = top; top = e; } } public void pop() { if(top == null) return; Elem temp = top.next; top.next = null; top = temp; } public int top() { if(top == null) return -1; return top.value; } public int getMin() { if(top == null) return -1; return top.min; } } |
Same solution but with encapsulation and null (instead of -1)
/* TODO: support comparable or use comparator.*/
public class MinStack
{
private Node top;
public Integer top()
{
if (top == null) return null;
return top.value;
}
public void push(int x)
{
if (top == null)
{
top = new Node(x, x, null);
return;
}
Node n = new Node(x, top.min, top);
top = n;
}
public Integer pop()
{
if (top == null) return null;
int x = top.value;
top = top.prev;
return x;
}
public Integer getMin()
{
if (top == null) return null;
return top.min;
}
private static class Node
{
public final int value;
public final int min;
public final Node prev;
public Node(int value, int min, Node prev)
{
this.value = value;
this.min = min;
this.prev = prev;
}
}
}
One would also need a magic wand to get this code work.
Yes that’s right, if we use PriorityQueue, push() and pop() won’t be constant time O(1), it will be logarithmic O(logn), where n is number of elements in the stack.
package base_alg;
public class MinStack {
private Node head;
public int getMin() {
return head.getMin();
}
public void push(int value) {
if (head == null) {
head = new Node(value);
} else {
head = new Node(value, head, Math.min(value, head.getMin()));
}
}
public int top() {
if (head == null) {
throw new NullPointerException();
}
return head.getValue();
}
public int pop() {
int value = top();
head = head.getNext();
return value;
}
}
class Node {
private int value;
private int min;
private Node next;
public Node(int value) {
this.value = value;
this.min = value;
}
public Node(int value, Node node, int min) {
this.next = node;
this.value = value;
this.min = min;
}
public void setNext(Node next) {
this.next = next;
}
public void setValue(int value) {
this.value = value;
}
public Node getNext() {
return next;
}
public int getValue() {
return value;
}
public int getMin() {
return min;
}
public void setMin(int min) {
this.min = min;
}
}
Will this code work? Suppose that when a new element is inserted, it is known that the min(x, top.min) = x.
In that case, the ‘min’ value for all the remaining elements of the stack are not updated. So when you pop an element from the stack you need to update the ‘min’ value for the new top with the ‘min’ value f the current top that is being removed.
Using min heap.
class MinStack {
public:
stack st;
priority_queue<int,vector,greater> pq;
void push(int x){
st.push(x);
pq.push(x);
}
void pop(){
if(st.top()==pq.top()){
st.pop();
pq.pop();
}
else{
st.pop();
}
}
int top(){
return st.top();
}
int getMin(){
return pq.top();
}
};
All the operations in the above example are constant time. Where is the iteration you’re seeing? If you don’t follow how the min is tracked in the stack values try working through the algorithm on paper.
Using a priority queue gives you a program that is correct but does not meet the constant time performance requirements. Whilst peek can be constant time both push and pop will be logarithmic.
public class MinStack {
PriorityQueue pq;
Stack st;
/** initialize your data structure here. */
public MinStack() {
pq=new PriorityQueue();
st=new Stack();
}
public void push(int x) {
pq.offer(x);
st.push(x);
}
public void pop() {
Integer x = st.pop();
pq.remove(x);
}
public int top() {
return st.peek();
}
public int getMin() {
return pq.peek();
}
}
I felt the code is all good, delivering to what is required. At a given point of time,/node leve, we need the min-value in the stack and every node carrying a property (Node.min) is satisfied O(1)
Here is my code. I guess it works fine !
class MinStack {
Node head;
public void push(int x) {
if(head == null) {
head = new Node(x);
head.min = x;
}
else {
Node temp = new Node(x);
if(temp.min > head.min) temp.min = head.min;
temp.next = head;
head = temp;
}
}
public void pop() {
if(head == null ) return ;
head = head.next;
}
public int top() {
if(head == null ) return Integer.MAX_VALUE;
return head.value;
}
public int getMin() {
if(head == null ) return Integer.MAX_VALUE;
return head.min;
}
}
class Node {
int value;
int min;
Node next;
Node(int x) { value = x; next = null; min = x;}
}
Actually, this works:
class MinStack {
int[] arr = new int [100];
int index = -1;
int[] min = new int [100];
public void push(int x) {
if (index == arr.length – 1) {
arr = Arrays.copyOf(arr, 2*arr.length);
min = Arrays.copyOf(min, 2*min.length);
}
index++;
arr[index] = x;
min[index] = index == 0 ? x : Math.min(x, min[index-1]);
}
public void pop() {
if(index == arr.length/2 – 1 && arr.length > 100) {
arr = Arrays.copyOf(arr, arr.length/2);
min = Arrays.copyOf(min, min.length/2);
}
index–;
}
public int top() {
if (index > -1) {
return arr[index];
}
else {
return -1;
}
}
public int getMin() {
if(index > -1) {
return min[index];
}
else {
return -1;
}
}
}
I guess you could add it to a HashMap, along with the number of times that min value appears.. so if the min value gets popped, you either remove it from the hash map if its value is 1, or decrement the # of times it appears
Just keep the min value is not enough, if your next pop removes the min value, then you need know the new min value, which still needs O(n) time to search
you’re right. You should have a minimum value declared in this class, and every time you push a new number to the stack, check if it is a lower value than the current min, and update that way, so when you call getMin it’s 0(1)
Am I having a brain fart? How is this retrieving the minimum value in constant runtime if it iterates through the entire stack? That is O(n) runtime.