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

问题描述:

实现一个队列,使得它的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),但是因为并不是在操作每一个元素的时候都需要倒转,所以平均下来整个算法的三个函数的时间复杂度是常数。

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

实现

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;
    }
}

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

结束!

点赞