Получение элемента Min в стеке за время O(1)
причина, по которой я задаю этот вопрос, заключается в том, что я не понимаю, почему то, как я думаю, не может быть применено к этому конкретному вопросу
"как бы вы спроектировать стека, который, в дополнение к push и pop, также есть функция min, которая возвращает минимальный элемент? Push, pop и min должны работать в O (1) time"
мое основное решение:не было бы возможным, если бы у нас была переменная в стек класс, что всякий раз, когда мы были нажатие элемента в стек мы бы проверить, если это меньше чем наш мин переменной. Если это присвоить значение min, если не игнорировать.
вы все равно получите O (1), поскольку функция min будет;
int getMinimum(){
return min;
}
почему это решение никогда не упоминается, или в чем виноват, как я думаю?
4 ответов
Это не сработало бы, если бы вы вытащили числа из стека.
Ex. 2,4,5,3,1. После того, как вы выкинете 1, каков ваш минимум?
решение сохранить стек минимумов, а не только одно значение. Если вы столкнулись со значением, которое меньше, чем равно текущему минимуму, вам нужно нажать его на min-stack.
Ex.
Push(4):
Stack: 4
Min-stack: 4
Push(2):
Stack: 4 2
Min-stack: 4 2
Push(2):
Stack: 4 2 2
Min-stack: 4 2 2
Push(5):
Stack: 4 2 2 5
Min-stack: 4 2 2
Push(3):
Stack: 4 2 2 5 3
Min-stack: 4 2 2
Push(1):
Stack: 4 2 2 5 3 1
Min-stack: 4 2 2 1
Pop():
Stack: 4 2 2 5 3
Min-stack: 4 2 2
Pop():
Stack: 4 2 2 5
Min-stack: 4 2 2
Pop():
Stack: 4 2 2
Min-stack: 4 2 2
Pop():
Stack: 4 2
Min-stack: 4 2
Pop():
Stack: 4
Min-stack: 4
использовать связанный список, чтобы отслеживать минимальное значение, которое будет в голове.
обратите внимание, что linkedlist.app= append (мы помещаем значение в хвост ). LinkedList не.pre =prepend (мы ставим значение в качестве главы linkedlist)
стек общественных класса {
int[] elements;
int top;
Linkedlists min;
public Stack(int n) {
elements = new int[n];
top = 0;
min = new Linkedlists();
}
public void realloc(int n) {
int[] tab = new int[n];
for (int i = 0; i < top; i++) {
tab[i] = elements[i];
}
elements = tab;
}
public void push(int x) {
if (top == elements.length) {
realloc(elements.length * 2);
}
if (top == 0) {
min.pre(x);
} else if (x < min.head.data) {
min.pre(x);
} else {
min.app(x);
}
elements[top++] = x;
}
public int pop() {
int x = elements[--top];
if (top == 0) {
}
if (this.getMin() == x) {
min.head = min.head.next;
}
elements[top] = 0;
if (4 * top < elements.length) {
realloc((elements.length + 1) / 2);
}
return x;
}
public void display() {
for (Object x : elements) {
System.out.print(x + " ");
}
}
public int getMin() {
if (top == 0) {
return 0;
}
return this.min.head.data;
}
public static void main(String[] args) {
Stack stack = new Stack(4);
stack.push(2);
stack.push(3);
stack.push(1);
stack.push(4);
stack.push(5);
stack.pop();
stack.pop();
stack.pop();
stack.push(1);
stack.pop();
stack.pop();
stack.pop();
stack.push(2);
System.out.println(stack.getMin());
stack.display();
}
}
Я нашел это решение здесь
struct StackGetMin {
void push(int x) {
elements.push(x);
if (minStack.empty() || x <= minStack.top())
minStack.push(x);
}
bool pop() {
if (elements.empty()) return false;
if (elements.top() == minStack.top())
minStack.pop();
elements.pop();
return true;
}
bool getMin(int &min) {
if (minStack.empty()) {
return false;
} else {
min = minStack.top();
return true;
}
}
stack<int> elements;
stack<int> minStack;
};
мы определяем переменную minEle, которая хранит текущий минимальный элемент в стеке. Теперь интересная часть заключается в том, как обрабатывать случай, когда минимальный элемент удален. Чтобы справиться с этим, мы нажимаем "2x – minEle" в стек вместо x, чтобы предыдущий минимальный элемент можно было получить с помощью текущего minEle и его значения, хранящегося в стеке. Ниже приведены подробные шаги и объяснение работы.
Push (x): вставки x в верхней части стек.
If stack is empty, insert x into the stack and make minEle equal to x.
If stack is not empty, compare x with minEle. Two cases arise:
If x is greater than or equal to minEle, simply insert x.
If x is less than minEle, insert (2*x – minEle) into the stack
and make minEle equal to x.
For example, let previous minEle was 3.
Now we want to insert 2. We update minEle as 2 and insert 2*2 – 3 = 1 into the stack.
Pop (): удаляет элемент из верхней части стека.
Remove element from top. Let the removed element be y. Two cases arise:
If y is greater than or equal to minEle,
the minimum element in the stack is still minEle.
If y is less than minEle, the minimum element now becomes
(2*minEle – y), so update (minEle = 2*minEle – y).
This is where we retrieve previous minimum from current minimum
and its value in stack. For example, let the element to be
removed be 1 and minEle be 2. We remove 1 and update minEle as 2*2 – 1 = 3.
/ Java program to implement a stack that supports
// getMinimum() in O(1) time and O(1) extra space.
import java.util.*;
// A user defined stack that supports getMin() in
// addition to push() and pop()
class MyStack
{
Stack<Integer> s;
Integer minEle;
// Constructor
MyStack() { s = new Stack<Integer>(); }
// Prints minimum element of MyStack
void getMin()
{
// Get the minimum number in the entire stack
if (s.isEmpty())
System.out.println("Stack is empty");
// variable minEle stores the minimum element
// in the stack.
else
System.out.println("Minimum Element in the " +
" stack is: " + minEle);
}
// prints top element of MyStack
void peek()
{
if (s.isEmpty())
{
System.out.println("Stack is empty ");
return;
}
Integer t = s.peek(); // Top element.
System.out.print("Top Most Element is: ");
// If t < minEle means minEle stores
// value of t.
if (t < minEle)
System.out.println(minEle);
else
System.out.println(t);
}
// Removes the top element from MyStack
void pop()
{
if (s.isEmpty())
{
System.out.println("Stack is empty");
return;
}
System.out.print("Top Most Element Removed: ");
Integer t = s.pop();
// Minimum will change as the minimum element
// of the stack is being removed.
if (t < minEle)
{
System.out.println(minEle);
minEle = 2*minEle - t;
}
else
System.out.println(t);
}
// Insert new number into MyStack
void push(Integer x)
{
if (s.isEmpty())
{
minEle = x;
s.push(x);
System.out.println("Number Inserted: " + x);
return;
}
// If new number is less than original minEle
if (x < minEle)
{
s.push(2*x - minEle);
minEle = x;
}
else
s.push(x);
System.out.println("Number Inserted: " + x);
}
};
// Driver Code
public class Main
{
public static void main(String[] args)
{
MyStack s = new MyStack();
s.push(3);
s.push(5);
s.getMin();
s.push(2);
s.push(1);
s.getMin();
s.pop();
s.getMin();
s.pop();
s.peek();
}
}
как работает этот подход?
когда вставляемый элемент меньше minEle, мы вставляем "2x-minEle". Важно отметить, что 2x-minEle всегда будет меньше x (доказано ниже), т. е. новая минеля, и при появлении этого элемента мы увидим, что произошло что-то необычное, поскольку выскочивший элемент меньше, чем minEle. Таким образом, мы будем обновлять minEle
как 2 * x-minEle меньше, чем x в push()?
x
// добавление x с обеих сторон
x-minEle + x
2 * x-minEle
мы можем заключить 2 * x-minEle
при появлении, если мы найдем элемент (y) меньше, чем текущая минела, мы найдем новую минелу = 2 * минеле – y.
как предыдущий минимальный элемент, prevMinEle, 2 * minEle-y?
в pop () является y выскочил элемент?
/ / мы нажали y как 2x-prevMinEle. Вот!--4-->
// prevMinEle является минеле до y был вставлен
y = 2 * x-prevMinEle
// значение minEle было сделано равным x minEle = x .
новая минела = 2 * minEle-y
= 2*x - (2*x - prevMinEle)
= prevMinEle // This is what we wanted