Supponiamo che lo stack su cui lavoreremo sia questo:
6 , minvalue=2
2 , minvalue=2
5 , minvalue=3
3 , minvalue=3
9 , minvalue=7
7 , minvalue=7
8 , minvalue=8
Nella rappresentazione sopra lo stack è costruito solo dal valore di sinistra il [minvalue] del valore di destra è scritto solo a scopo illustrativo che sarà memorizzato in una variabile.
Il problema attuale è quando il valore che è il valore minimo viene rimosso a quel punto come possiamo sapere qual è il prossimo elemento minimo senza iterare sullo stack.
Come per esempio nel nostro stack quando 6 vengono spuntati, sappiamo che questo non è l'elemento minimo perché l'elemento minimo è 2, quindi possiamo rimuoverlo in sicurezza senza aggiornare il nostro valore minimo.
Ma quando inseriamo 2, possiamo vedere che il valore minimo è 2 in questo momento e se questo viene saltato fuori, dobbiamo aggiornare il valore minimo a 3.
point1:
Ora, se osservi attentamente, dobbiamo generare minvalue = 3 da questo particolare stato [2, minvalue = 2]. o se vai più depper nello stack dobbiamo generare minvalue = 7 da questo particolare stato [3, minvalue = 3] o se vai più depper nello stack, allora dobbiamo generare minvalue = 8 da questo particolare stato [7, minvalue = 7]
Hai notato qualcosa in comune in tutti i 3 casi precedenti, il valore che dobbiamo generare dipende da due variabili che sono entrambe uguali. Corretta. Perché succede perché quando spingiamo un elemento più piccolo dell'attuale minvalue, in pratica inseriamo quell'elemento nello stack e aggiornato lo stesso numero anche in minvalue.
point2:
Quindi fondamentalmente stiamo memorizzando duplicati dello stesso numero una volta nello stack e una volta nella variabile minvalue. Dobbiamo concentrarci sull'evitare questa duplicazione e memorizzare qualcosa di utile nello stack o nel minvalue per generare il minimo precedente come mostrato in CASES sopra.
Concentriamoci su cosa dovremmo memorizzare nello stack quando il valore da memorizzare in push è inferiore al minmumvalue. Chiamiamo questa variabile y, quindi ora il nostro stack avrà un aspetto simile a questo:
6 , minvalue=2
y1 , minvalue=2
5 , minvalue=3
y2 , minvalue=3
9 , minvalue=7
y3 , minvalue=7
8 , minvalue=8
Li ho rinominati come y1, y2, y3 per evitare confusione che tutti avranno lo stesso valore.
Point3:
Ora proviamo a trovare alcuni vincoli su y1, y2 e y3. Ricordi esattamente quando dobbiamo aggiornare il minvalue mentre facciamo pop (), solo quando abbiamo estratto l'elemento che è uguale al minvalue. Se inseriamo qualcosa di più grande del minvalue, non dobbiamo aggiornare minvalue. Quindi, per attivare l'aggiornamento di minvalue, y1, y2 e y3 dovrebbero essere più piccoli del valore min corrispondente. [Stiamo considerando l'uguaglianza per evitare duplicati [Point2]] quindi il vincolo è [y <minValue].
Ora torniamo a popolare y, dobbiamo generare un valore e inserire y al momento del push, ricorda. Prendiamo il valore che sta arrivando per push come x, che è minore di prevMinvalue, e il valore che effettivamente inseriremo nello stack per essere y. Quindi una cosa è ovvia che newMinValue = x e y <newMinvalue.
Ora dobbiamo calcolare y (ricorda che y può essere qualsiasi numero inferiore a newMinValue (x) quindi dobbiamo trovare un numero che possa soddisfare il nostro vincolo) con l'aiuto di prevMinvalue e 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].
Quindi, al momento di premere x, se è inferiore a prevMinvalue, premiamo y [2 * x-prevMinValue] e aggiorniamo newMinValue = x.
E al momento del pop se lo stack contiene qualcosa di meno di minValue, allora questo è il nostro trigger per aggiornare minVAlue. Dobbiamo calcolare prevMinValue da curMinValue e y. y = 2 * curMinValue - prevMinValue [Provato] prevMinVAlue = 2 * curMinvalue - y.
2 * curMinValue - y è il numero che dobbiamo aggiornare ora a prevMinValue.
Il codice per la stessa logica è condiviso di seguito con O (1) tempo e O (1) complessità spaziale.
// 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;
}