假设我们将要处理的堆栈是这样的:
6 , minvalue=2
2 , minvalue=2
5 , minvalue=3
3 , minvalue=3
9 , minvalue=7
7 , minvalue=7
8 , minvalue=8
在上面的表示中,堆栈仅由左值构建,右值[最小值]仅用于说明目的,将存储在一个变量中。
实际问题是当最小值被移除时:在这一点上,我们如何知道下一个最小元素而不必迭代堆栈。
例如,在我们的堆栈中弹出6时,我们知道这不是最小元素,因为最小元素是2,所以我们可以安全地删除此元素而不更新最小值。
但是当我们弹出2时,我们可以看到当前的最小值是2,如果将其弹出,则需要将最小值更新为3。
点1:
Now if you observe carefully we need to generate minvalue=3 from this particular state [2 , minvalue=2].
Or if you go deeper in the stack we need to generate minvalue=7 from this particular state [3 , minvalue=3]
or if you go deeper still in the stack then we need to generate minvalue=8 from this particular state [7 , minvalue=7]
Did you notice something in common in all of the above three cases? The value which we need to generate depends upon two variable which are both equal. Correct.
Why is this happening because when we push some element smaller then the current minvalue, then we basically push that element in the stack and updated the same number in minvalue also.
点二:
So we are basically storing duplicate of the same number once in stack and once in minvalue variable.
We need to focus on avoiding this duplication and store something useful data in the stack or the minvalue to generate the previous minimum as shown in CASES above.
Let s focus on what should we store in stack when the value to store in push is less than the minimum value.
Let s name this variable y, so now our stack will look something like this:
6 , minvalue=2
y1 , minvalue=2
5 , minvalue=3
y2 , minvalue=3
9 , minvalue=7
y3 , minvalue=7
8 , minvalue=8
我将它们重命名为y1,y2,y3,以避免混淆,因为它们都具有相同的值。
第三点:
Now let s try to find some constraint s over y1, y2 and y3.
Do you remember when exactly we need to update the minvalue while doing pop(), only when we have popped the element which is equal to the minvalue.
If we pop something greater than the minvalue then we don t have to update minvalue.
So to trigger the update of minvalue, y1,y2&y3 should be smaller than there corresponding minvalue. [We are avoiding equality to avoid duplicate[Point2]]
so the constrain is [ y < minValue ].
Now let s come back to populate y, we need to generate some value and put y at the time of push, remember.
Let s take the value which is coming for push to be x which is less that the prevMinvalue, and the value which we will actually push in stack to be y.
So one thing is obvious that the newMinValue=x, and y < newMinvalue.
现在,我们需要计算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。
And at the time of pop if the stack contains something less than the minValue then that s our trigger to update the minValue.
We have to calculate prevMinValue from the curMinValue and y.
y = 2*curMinValue - prevMinValue [Proved]
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
";
// variable minEle stores the minimum element
// in the stack.
else
cout <<"Minimum Element in the stack is: "
<< minEle << "
";
}
// 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
";
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 << "
";
minEle = 2*minEle - t;
}
else
cout << t << "
";
}
// 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 << "
";
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 << "
";
}
};
// 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;
}