在O(1)中以模式堆栈

时间:2014-03-09 23:54:14

标签: statistics stack

有没有什么方法可以跟踪堆栈并获得模式在O(1)时间?

我知道我已经尝试过实现Min或Max Stack。但这个对我来说是新的。有什么想法??

1 个答案:

答案 0 :(得分:0)

这个想法与min-stack或max-stack相同,只是现在我们必须跟踪堆栈中元素的数量,以便我们可以决定新推送的元素是否改变了模式。 (您可以将此概括为可以提供(可能是有状态的)函数(currentValue, beingPushed) -> nextValue的任何操作,并保证弹出返回到先前的值。)

public class ModeStack<T> {
    private final Deque<T> stack = new ArrayDeque<>(), modeStack = new ArrayDeque<>();
    private final Map<T, Integer> count = new HashMap<>();
    public ModeStack() {}
    public void push(T t) {
        stack.push(t);
        int tCount = count.getOrDefault(t, 0)+1;
        count.put(t, tCount);
        if (modeStack.isEmpty())
            modeStack.push(t);
        else
            modeStack.push(tCount > count.get(modeStack.peek())
                    ? t : modeStack.peek());
    }
    //throws NoSuchElementException if stack is empty
    public T pop() {
        int newCount = count.get(stack.peek())-1;
        //remove unneeded map entries to prevent memory retention
        if (newCount == 0)
            count.remove(stack.peek());
        else
            count.put(stack.peek(), newCount);
        modeStack.pop();
        return stack.pop();
    }
    //returns null if stack is empty; ties broken by earliest-value-first
    public T mode() {
        return modeStack.peek();
    }

    public static void main(String[] args) {
        ModeStack<Integer> s = new ModeStack<>();
        s.push(1);
        System.out.println(s.mode());
        s.push(2);
        s.push(2);
        System.out.println(s.mode());
        s.pop();
        System.out.println(s.mode());
    }
}

维护地图不会改变渐近空间复杂度,因为在最坏的情况下,所有键都映射到1并且映射的大小为n - 但元素堆栈和模式堆栈的大小也为{{1} },所以总空间使用量为n