如何维护堆栈,以便每当从堆栈弹出时,您知道堆栈中的最小元素?该算法应具有恒定的复杂度
提前致谢
答案 0 :(得分:3)
好的,这就是你需要做的......
您需要维护一些data structure
包含您插入的每个元素的信息,插入该元素时的minimum
和second minimum
值是什么。
所以,你想要这样的信息: -
对于推送的每个元素 - >
当您从堆栈中pop
该元素时,将需要此信息。所以,您会知道,您是否popping
最小值...如果是,那么您可以替换在推送此元素之前,minimum
的当前minimum value
值。如果没有,则此时minimum
值不会发生变化..
例如: -
假设您当前在堆栈中有以下元素: -
[3, 5, 7, 9, 2, 4]
然后按值8 ..然后你有两个值要维护.. (推出8之前的最小值,即2,以及8之后的miminum值 插入,即2): -
min_value_before_push = min(stack)
push 8
min_value_after_push = min(stack)
如果您按值1 ,则minimum_before_insertion
为2,
并且minimum_after_insertion
是1: -
min_value_before_push = 2
min_value_after_push = 1
现在你的筹码是: -
[1, 8, 3, 5, 7, 9, 2, 4]
现在,如果您 pop
,您会看到 value 1
: -
min_value_before_push = 2
min_value_after_push = 1
因此,弹出将改变最小值,因此,您更改当前最小值minimum_value_before_push
为1 ..所以,您的最小值再次为2 ..
您当前的筹码变为: -
[8, 3, 5, 7, 9, 2, 4]
现在,让我们检查此算法是否适用于duplicate
元素: -
假设您想再次推送value 2
..
min_value_before_push = 2
min_value_after_push = 2
然后你继续pop
,你看到value 2
,min_value_after_push
是2,所以这意味着弹出它会改变最小值..所以你用这个值替换min_value_before_push
,也是2 ..这就是我们想要的......
注意: - 此算法的一个好处是,您不需要进行太多比较..只需在推送时与current_minimum_value
进行比较..并与{进行比较当您current_minimum_value
..
您可以尝试继续思考pop
可以拥有什么......
答案 1 :(得分:2)
免责声明:禁止使用空值(就像ArrayDeque一样),并且未经过严格测试。
import java.util.ArrayDeque;
public class PessimisticStack<T extends Comparable<? super T>> {
private class Entry {
private Entry(T t, T minNow) {
this.t = t;
this.minNow = minNow;
}
private final T t;
private final T minNow;
}
private final ArrayDeque<Entry> deque;
public PessimisticStack() {
deque = new ArrayDeque<Entry>();
}
public PessimisticStack(int initialCapacity) {
deque = new ArrayDeque<Entry>(initialCapacity);
}
public void push(T t) {
if (t == null) throw new NullPointerException();
Entry entry = null;
if (deque.isEmpty()) {
entry = new Entry(t, t);
}
else {
T prevMinimum = deque.peek().minNow;
T newMinimum = null;
if (t.compareTo(prevMinimum) < 0) {
newMinimum = t;
}
else {
newMinimum = prevMinimum;
}
entry = new Entry(t, newMinimum);
}
deque.push(entry);
}
public T pop() {
return deque.pop().t;
}
public T getMinimum() {
Entry entry = deque.peek();
return (entry == null ? null : entry.minNow);
}
}
使用示例
PessimisticStack<String> stack = new PessimisticStack<String>();
stack.push("Zebra");
stack.push("Elephant");
stack.push("Bryan");
stack.push("Adam");
stack.push("Calvin");
String calvin = stack.pop();
// "Adam"
System.err.println(stack.getMinimum());
stack.push("Aaron");
// "Aaron"
System.err.println(stack.getMinimum());
String aaron = stack.pop();
// "Adam"
System.err.println(stack.getMinimum());
String adam = stack.pop();
// "Bryan"
System.err.println(stack.getMinimum());
答案 2 :(得分:1)
在推送元素minStack
时使用另一个堆栈,比如val
,检查是否val < minStack.peek()
,如果是,请同时将val
推送到minStack
;当从stack
弹出时,请检查值pop,例如pop_val
,如果minStack.pop()
则执行pop_val == minStack.peek()
。
既然我们有一个minStack
可以将所有local-min-element
保留在特定的时间点(直到下一次推送到minStack的时候),我们可以很容易地找出何时从minStack弹出通过检查堆栈的顶部是否为local-min-element
,已经在上面介绍过了。
但是,只有当所有元素彼此都是唯一的时,该方法才能正常工作,否则,它会更难做,提示,使用计数器:)。