实现一个队列,使得push_rear(), pop_front() 和get_min()的时间复杂度为O

Posted ChainingBlocks

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了实现一个队列,使得push_rear(), pop_front() 和get_min()的时间复杂度为O相关的知识,希望对你有一定的参考价值。

问题描述:

实现一个队列,使得它的push_rear(), pop_front() 和get_min() 这三个函数的时间复杂的为常数(即O(1))。

分析:

在leetcode上面有类似的题目,但是其所要求的是实现一个栈(stack)而不是队列。

这里将使用两个栈来作为辅助数据结构。第一个栈专门用来接收新来的数据,第二个栈专门接收第一个栈中的数据。每一次都把第一个栈中的所有数据倒转到第二个中。数据永远从第二个栈中pop出去。

具体举例来看:现在四个数字[1, 5, 2, 4] (4是最早到达的数据)依次压入栈中,每压入一个数字的时候,在其旁边(黄色背景)使用另一个数字记录当前栈中最小的值。所以,从下图中,当压入数字5的时候,当前栈中最小的值是2,所以其旁边的数字为2.

四个数字入栈之后,把它们分别弹出然后再次入栈到第二个栈中。黄色背景的数值依然是记录当前栈中最小的数字。当需要pop front操作的时候,把第二个栈中top元素弹出。

这时候发现,这三个函数push_rear(), pop_front() 和get_min()的时间复杂度是为O(0)的。算法运行期间间歇性的将数据从栈1中倒转到栈2中,这个操作所用的时间复杂度为O(n),但是因为并不是在操作每一个元素的时候都需要倒转,所以平均下来整个算法的三个函数的时间复杂度是常数。

实现

import java.util.EmptyStackException;
import java.util.Stack;

public class ContantQueue 

    private Stack<Value> s1 = new Stack<>();
    private Stack<Value> s2 = new Stack<>();


    public void pushRear(int value)
        System.out.println("input number: "+value);
        pushRear(s1, value);
    

    private void pushRear(Stack<Value> s, int value)
        if(s.empty())
            s.push(new Value(value, value));
        else
            if(value > s.peek().min)
                s.push(new Value(value, s.peek().min));
            else
                s.push(new Value(value, value));
            
        
    

    public int popFront()
        if(empty()) throw new EmptyStackException();
        return s2.pop().value;
    

    public int getMin()
        if(empty()) throw new EmptyStackException();
        return s2.peek().min;
    

    public boolean empty()
        if(s2.empty())
            transferNums();
        
        if(s2.empty()) return true;
        else return false;
    

    private void transferNums()
        if(s1.empty()) return;
        while(!s1.empty())
            pushRear(s2, s1.pop().value);
        
    

    class Value
        int value;
        int min;

        public Value()

        public Value(int value, int min)
            this.value = value;
            this.min = min;
        
    

    public static void main(String[] args) 
        ContantQueue queue = new ContantQueue();

        queue.pushRear(4);
        queue.pushRear(2);
        queue.pushRear(5);
        queue.pushRear(1);

        assert queue.popFront() == 4;
        assert queue.popFront() == 2;
        assert queue.popFront() == 5;
        assert queue.popFront() == 1;

        queue.pushRear(6);
        queue.pushRear(2);
        queue.pushRear(9);
        queue.pushRear(7);

        assert queue.popFront() == 6;
        assert queue.getMin() == 2;
        assert queue.popFront() == 2;
        assert queue.getMin() == 7;

        queue.pushRear(16);
        queue.pushRear(8);

        assert queue.popFront() == 9;
        assert queue.popFront() == 7;
        assert queue.popFront() == 16;
        assert queue.popFront() == 8;
    

该代码实现只适用于单线程。

结束!

以上是关于实现一个队列,使得push_rear(), pop_front() 和get_min()的时间复杂度为O的主要内容,如果未能解决你的问题,请参考以下文章

用两个队列实现一个栈

用两个栈实现队列的POP和PUSH操作

使用 push(x)、pop() 和 pop_max() 方法实现队列

用栈实现队列

用栈实现队列

用两个栈来实现一个队列,完成队列的Push和Pop操作。