Давайте предположим, что стек, над которым мы будем работать, такой:
6 , minvalue=2
2 , minvalue=2
5 , minvalue=3
3 , minvalue=3
9 , minvalue=7
7 , minvalue=7
8 , minvalue=8
В вышеприведенном представлении стек строится только из левого значения, а правое значение [minvalue] записывается только в целях иллюстрации, которое будет храниться в одной переменной.
Фактическая проблема заключается в том, что когда значение, являющееся минимальным значением get, удаляется в этот момент, как мы можем узнать, каков следующий минимальный элемент, без итерации по стеку.
Как, например, в нашем стеке, когда 6 get выскочили, мы знаем, что это не минимальный элемент, потому что минимальный элемент равен 2, поэтому мы можем безопасно удалить его, не обновляя наше минимальное значение.
Но когда мы выскакиваем 2, мы можем видеть, что минимальное значение равно 2 прямо сейчас, и если этот get выскочил, нам нужно обновить минимальное значение до 3.
Point1:
Теперь, если вы внимательно посмотрите, нам нужно сгенерировать minvalue = 3 из этого конкретного состояния [2, minvalue = 2].
или если вы углубитесь в стек, нам нужно сгенерировать minvalue = 7 из этого конкретного состояния [3, minvalue = 3]
или если вы углубитесь в стек, то нам нужно сгенерировать minvalue = 8 из этого конкретного состояния [7, minvalue = 7]
Заметили ли вы что-то общее во всех вышеупомянутых 3 случаях, значение, которое нам нужно сгенерировать, зависит от двух переменных, которые оба равны. Правильный.
Почему это происходит, потому что, когда мы помещаем какой-то элемент меньше текущего минимального значения, тогда мы в основном помещаем этот элемент в стек и обновляем также то же число в минимальном значении.
Point2:
Таким образом, мы в основном храним дубликаты одного и того же числа один раз в стеке и один раз в переменной минимального значения.
Нам нужно сосредоточиться на том, чтобы избежать этого дублирования и хранить что-то полезное в стеке или в минимальном значении, чтобы сгенерировать предыдущий минимум, как показано в CASES выше.
Давайте сосредоточимся на том, что мы должны хранить в стеке, когда значение для сохранения в push меньше, чем minmumvalue.
Давайте назовем эту переменную y, так что теперь наш стек будет выглядеть примерно так:
6 , minvalue=2
y1 , minvalue=2
5 , minvalue=3
y2 , minvalue=3
9 , minvalue=7
y3 , minvalue=7
8 , minvalue=8
Я переименовал их в y1, y2, y3, чтобы избежать путаницы, что все они будут иметь одинаковое значение.
Point3:
Теперь давайте попробуем найти некоторые ограничения для y1, y2 и y3.
Помните ли вы, когда именно нам нужно обновить minvalue при выполнении pop (), только когда мы выдвинули элемент, равный minvalue.
Если мы добавляем что-то большее, чем minvalue, нам не нужно обновлять minvalue.
Таким образом, чтобы вызвать обновление minvalue, y1, y2 & y3 должны быть меньше, чем соответствующее minvalue. [Мы избегаем дублирования, чтобы избежать дублирования [Point2]]
поэтому ограничение [y
Теперь давайте вернемся к заполнению y, нам нужно сгенерировать какое-то значение и поставить y во время нажатия, запомните.
Давайте возьмем значение, которое придет для push, равным x, которое меньше значения prevMinvalue, и значение, которое мы фактически вставим в стек, равным y.
Таким образом, очевидно, что newMinValue = x, а y
Теперь нам нужно вычислить y (помните, что y может быть любым числом, которое меньше newMinValue (x), поэтому нам нужно найти некоторое число, которое может удовлетворить наше ограничение) с помощью prevMinvalue и x (newMinvalue).
Let's do the math:
x < prevMinvalue [Given]
x - prevMinvalue < 0
x - prevMinValue + x < 0 + x [Add x on both side]
2*x - prevMinValue < x
this is the y which we were looking for less than x(newMinValue).
y = 2*x - prevMinValue. 'or' y = 2*newMinValue - prevMinValue 'or' y = 2*curMinValue - prevMinValue [taking curMinValue=newMinValue].
Таким образом, во время нажатия x, если оно меньше значения prevMinvalue, мы нажимаем y [2 * x-prevMinValue] и обновляем newMinValue = x.
И во время всплывающего окна, если в стеке содержится что-то меньшее minValue, это наш триггер для обновления minVAlue.
Мы должны вычислить prevMinValue из curMinValue и y.
y = 2 * curMinValue - prevMinValue [Доказано]
prevMinVAlue = 2 * curMinvalue - y.
2 * curMinValue - y - это число, которое нам нужно обновить сейчас до prevMinValue.
Код для той же логики представлен ниже с O (1) временем и O (1) пространственной сложностью.
// C++ program to implement a stack that supports
// getMinimum() in O(1) time and O(1) extra space.
#include <bits/stdc++.h>
using namespace std;
// A user defined stack that supports getMin() in
// addition to push() and pop()
struct MyStack
{
stack<int> s;
int minEle;
// Prints minimum element of MyStack
void getMin()
{
if (s.empty())
cout << "Stack is empty\n";
// variable minEle stores the minimum element
// in the stack.
else
cout <<"Minimum Element in the stack is: "
<< minEle << "\n";
}
// Prints top element of MyStack
void peek()
{
if (s.empty())
{
cout << "Stack is empty ";
return;
}
int t = s.top(); // Top element.
cout << "Top Most Element is: ";
// If t < minEle means minEle stores
// value of t.
(t < minEle)? cout << minEle: cout << t;
}
// Remove the top element from MyStack
void pop()
{
if (s.empty())
{
cout << "Stack is empty\n";
return;
}
cout << "Top Most Element Removed: ";
int t = s.top();
s.pop();
// Minimum will change as the minimum element
// of the stack is being removed.
if (t < minEle)
{
cout << minEle << "\n";
minEle = 2*minEle - t;
}
else
cout << t << "\n";
}
// Removes top element from MyStack
void push(int x)
{
// Insert new number into the stack
if (s.empty())
{
minEle = x;
s.push(x);
cout << "Number Inserted: " << x << "\n";
return;
}
// If new number is less than minEle
if (x < minEle)
{
s.push(2*x - minEle);
minEle = x;
}
else
s.push(x);
cout << "Number Inserted: " << x << "\n";
}
};
// Driver Code
int main()
{
MyStack s;
s.push(3);
s.push(5);
s.getMin();
s.push(2);
s.push(1);
s.getMin();
s.pop();
s.getMin();
s.pop();
s.peek();
return 0;
}