在上一篇文章中实现了
使用O(1)时间和O(n)的额外空间的方法getMin()。Stack(篇3)设计一个栈能够在O(1)的时间内getMin
在本文中,讨论了一种支持O(1)额外空间的最新方法。我们定义一个变量minEle,它存储堆栈中的当前最小元素。现在的问题是如何处理最小元素被删除的情况。为了处理这个,我们将“2x-minEle”推入堆栈而不是x,以便可以使用当前的minEle检索先前的最小元素,并将其值存储在堆栈中。
以下是算法的核心部分。
Push(x):
①如果堆栈为空,则将x插入堆栈,并使minEle等于x。
②如果堆栈不为空,请将x与minEle进行比较。出现两种情况:
③如果x大于或等于minEle,只需插入x。
④如果x小于minEle,则将(2 * x - minEle) 压到栈中,将minEle的值更新为 x。
Pop():
①从顶部移除元素 将删除的元素设为y。出现两种情况:
②如果y大于minEle,则堆栈中的最小元素仍为minEle。
③如果y小于或等于minEle,则最小元素现在变为(2 * minEle - y),因此更新minEle = 2 * minEle - y。
得到了前一个minEle。
重点:
①如果到目前为止,堆栈不保持元素的实际值。
②实际最小元素始终存储在minEle中
例如数组:{4,2,1,1,5,-1}
插入
下图中黄色部分是放到栈中的值,绿色部分是当前minEle的值变化情况实际上minEle的值并不需要栈来保存,只需要一个变量来保存每次最顶上的就可以。红色部分是压栈的顺序。
①当栈为空时,放入的第一个元素赋值给 minEle。将4压入栈中当前最小值 minEle=4。
② 遍历到2时,将2与minEle比较,2<
minEle, 此时将 2*2-minEle=0 压入栈中,minEle=2。
③ 遍历到1时,将1与minEle=2比较,1<
minEle,此时将 1*2-minEle=0 压入栈中,minEle=1。
④ 遍历到5时,将5与minEle=1比较,5>
minEle,直接压栈,minEle不变。
⑤遍历到-1时,将-1与minEle=1比较,-1<
minEle,此时将 -1*2-minEle=-3压入栈中,minEle=-1。
删除
①删除栈顶元素 -3,比较-3与minEle的值,发现 -3<
minEle=-1,此时原来栈顶元素应该是:-3-2*minEle=-1 , 更新minEle=2*minElen+3=1.
②删除栈顶元素5,5>
minEle,直接删除。
代码
package Stack;
import java.util.Stack;
public class Mystack {
public static int minEle=0;
Stack< Integer> stack;
public static void main(String[] args) {
// TODO Auto-generated method stub
Mystack stack=new Mystack(new Stack<Integer>());
stack.push(3);
stack.push(4);
stack.push(2);
stack.push(1);
stack.push(5);
System.out.println(stack.getMin());
stack.pop();
stack.pop();
System.out.println(stack.getMin());
stack.pop();
stack.pop();
System.out.println(stack.getMin());
}
public Mystack(Stack<Integer> stack) {
this.stack = stack;
}
public void push(int num)
{
if(stack.isEmpty())
{
minEle=num;
stack.push(num);
}
else {
if(minEle<num)
stack.push(num);
else {
stack.push(2*num-minEle);
minEle=num;
}
}
}
public int pop()
{
if(!stack.isEmpty())
{
if(stack.peek()<=minEle)
{
minEle=2*minEle-stack.peek();
}
return stack.pop();
}
else {
return 0;
}
}
public int getMin()
{
return minEle;
}
}