Supongamos que la pila en la que trabajaremos es la siguiente:
6 , minvalue=2
2 , minvalue=2
5 , minvalue=3
3 , minvalue=3
9 , minvalue=7
7 , minvalue=7
8 , minvalue=8
En la representación anterior, la pila solo se construye con el valor de la izquierda, el [valor mínimo] del valor de la derecha se escribe solo con fines ilustrativos, que se almacenará en una variable.
El problema real es cuando el valor que es el valor mínimo obtenido se elimina en ese punto, ¿cómo podemos saber cuál es el siguiente elemento mínimo sin iterar sobre la pila?
Como, por ejemplo, en nuestra pila cuando aparecen 6 get, sabemos que este no es el elemento mínimo porque el elemento mínimo es 2, por lo que podemos eliminarlo de forma segura sin actualizar nuestro valor mínimo.
Pero cuando mostramos 2, podemos ver que el valor mínimo es 2 en este momento y si este mensaje aparece, entonces debemos actualizar el valor mínimo a 3.
Punto 1:
Ahora, si observa cuidadosamente, necesitamos generar minvalue = 3 a partir de este estado particular [2, minvalue = 2]. o si va a depper en la pila, necesitamos generar minvalue = 7 a partir de este estado particular [3, minvalue = 3] o si va más depper en la pila, entonces necesitamos generar minvalue = 8 a partir de este estado en particular [7, minvalue = 7]
¿Notó algo en común en los 3 casos anteriores? El valor que necesitamos generar depende de dos variables que son iguales. Correcto. ¿Por qué sucede esto? Porque cuando empujamos algún elemento más pequeño que el minvalue actual, básicamente empujamos ese elemento en la pila y también actualizamos el mismo número en minvalue.
Punto2:
Básicamente, estamos almacenando duplicados del mismo número una vez en la pila y una vez en la variable minvalue. Necesitamos enfocarnos en evitar esta duplicación y almacenar algo de datos útiles en la pila o el minvalue para generar el mínimo anterior como se muestra en CASOS arriba.
Centrémonos en lo que debemos almacenar en la pila cuando el valor para almacenar en push es menor que el valor mínimo. Vamos a nombrar esta variable y, por lo que ahora nuestra pila se verá así:
6 , minvalue=2
y1 , minvalue=2
5 , minvalue=3
y2 , minvalue=3
9 , minvalue=7
y3 , minvalue=7
8 , minvalue=8
Los he renombrado como y1, y2, y3 para evitar confusión de que todos tendrán el mismo valor.
Punto3:
Ahora intentemos encontrar algunas restricciones sobre y1, y2 e y3. ¿Recuerda cuándo exactamente necesitamos actualizar el minvalue mientras hacemos pop (), solo cuando hemos extraído el elemento que es igual al minvalue? Si sacamos algo mayor que el minvalue, entonces no tenemos que actualizar minvalue. Entonces, para activar la actualización de minvalue, y1, y2 & y3 deberían ser más pequeños que el minvalue correspondiente. [Estamos evitando la igualdad para evitar duplicar [Point2]] por lo que la restricción es [y <minValue].
Ahora volvamos a rellenar y, necesitamos generar algún valor y poner y en el momento de empujar, recuerda. Tomemos el valor que viene para empujar como x, que es menor que prevMinvalue, y el valor que realmente empujaremos en la pila es y. Así que una cosa es obvia que newMinValue = x, y y <newMinvalue.
Ahora necesitamos calcular y (recuerde que y puede ser cualquier número que sea menor que newMinValue (x) así que necesitamos encontrar algún número que pueda cumplir con nuestra restricción) con la ayuda de prevMinvalue yx (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].
Entonces, en el momento de presionar x si es menor que prevMinvalue, presionamos y [2 * x-prevMinValue] y actualizamos newMinValue = x.
Y en el momento del estallido, si la pila contiene algo menos que minValue, ese es nuestro disparador para actualizar minVAlue. Tenemos que calcular prevMinValue a partir de curMinValue e y. y = 2 * curMinValue - prevMinValue [probado] prevMinVAlue = 2 * curMinvalue - y.
2 * curMinValue - y es el número que necesitamos actualizar ahora al prevMinValue.
El código para la misma lógica se comparte a continuación con la complejidad de O (1) tiempo y O (1) espacio.
// 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;
}