代码随想录算法训练营day10|理论基础,232.用栈实现队列,225. 用队列实现栈

理论基础 

栈与队列理论基础

1、java中Stack 是容器么?

是容器。java.util.Stack<E>是Vector<E>集合的子类,底层物理结构是动态数组,线程安全。Stack 比 Vector 多了几个方法:

        (1) peek():查看栈顶元素,不弹出;

        (2)pop():弹出栈;

        (3)push():压入栈,即添加到链表的头。

2、栈里面的元素在内存中是连续分布的么?

栈是容器适配器,使用不同的底层容器,会影响到栈内数据在内存中的分布。缺省情况下的默认底层容器是deque,在内存中的数据分布不连续。


3、栈的实现:

Deque stack=new ArrayDeque();

Deque stack = new LinkedList();

双端队列 Deque 可用作 LIFO(后进先出)堆栈。应优先使用此接口而非遗留 Stack 类。在将Deque 用作 Stack 时,元素被推入 Deque 的开头并从 Deque 开头弹出。Stack 方法完全等效于 Deque 方法,如下表所示:

堆栈方法等效 Deque 方法
push(e)addFirst(e)
pop()removeFirst()
peek()peekFirst()

4、队列的实现:

Queue queue = new LinkedList();

Queue 除了基本的 Collection 操作外,还提供其他的插入、提取和检查操作。每个方法都存在两种形式:一种抛出异常(操作失败时),另一种返回一个特殊值(null / false)。

抛出异常返回特殊值
插入add(e)offer(e)
移除remove()poll()
检查element()peek()

Deque 接口扩展了 Queue 接口。在将 Deque 用作队列时,将得到 FIFO(先进先出)行为。Deque 接口提供插入、移除和检查元素的方法。

第一个元素(头部)最后一个元素(尾部)
抛出异常特殊值抛出异常特殊值
插入addFirst(e)offerFirst(e)addLast(e)offerLast(e)
移除removeFirst()pollFirst()removeLast()pollLast()
检查getFirst()peekFirst()getLast()peekLast()

此外,从 Queue 接口继承的方法完全等效于 Deque 方法。

Queue 方法等效 Deque 方法
add(e)addLast(e)
offer(e)offerLast(e)
remove()removeFirst()
poll()pollFirst()
element()getFirst()
peek()peekFirst()

​​​​​​​​​​​​​​

232.用栈实现队列

力扣

思路:

1. 输入栈+输出栈,实现队列。

2. push 操作:将数据放入输入栈in。pop操作:若输出栈out为空,则导入in的所有数据,弹出;若非空,直接弹出。

3. isEmpty判断:当in和out均为空时,队列为空。

4. peek 操作:若out为空,则导入in的所有数据,out.peek();若非空,直接peek()。

class MyQueue {
    Stack<Integer> in;
    Stack<Integer> out;

    public MyQueue() {
        in = new Stack<>();
        out = new Stack<>();
    }
    
    public void push(int x) {
        in.push(x);
    }
    
    public int pop() {
        dumpStackIn();
        return out.pop();
    }
    
    public int peek() {
        dumpStackIn();
        return out.peek();
    }
    
    public boolean empty() {
        return in.isEmpty() && out.isEmpty();
    }

    private void dumpStackIn(){//如果out为空,就将in的元素全部加入out中
        if(!out.isEmpty()) return;
        while(!in.isEmpty()) out.push(in.pop());
    }
}

/**
 * Your MyQueue object will be instantiated and called as such:
 * MyQueue obj = new MyQueue();
 * obj.push(x);
 * int param_2 = obj.pop();
 * int param_3 = obj.peek();
 * boolean param_4 = obj.empty();
 */

225. 用队列实现栈

力扣

思路: 

1. 队列 queue1 用来实现操作,队列 queue2 用来在操作过程中暂时保存其他元素。

2. push 操作:queue1.push()。pop 操作:当 queue2 为空时,先把 queue1 的所有元素倒着存到 queue2,然后 queue2.pop(),最后将元素放回 queue1。

//两个Queue
class MyStack {
    Queue<Integer> que1;
    Queue<Integer> que2;

    public MyStack() {
        que1 = new LinkedList<>();
        que2 = new LinkedList<>();
    }
    
    public void push(int x) {
        que2.offer(x); // 先放在辅助队列中
        while (!que1.isEmpty()){
            que2.offer(que1.poll());
        }
        Queue<Integer> temp = que1;
        que1 = que2;
        que2 = temp; // 交换que1和que2,将元素都放到que1中
    }
    
    public int pop() {
        return que1.poll();
    }
    
    public int top() {
        return que1.peek();
    }
    
    public boolean empty() {
        return que1.isEmpty();
    }
}

/**
 * Your MyStack object will be instantiated and called as such:
 * MyStack obj = new MyStack();
 * obj.push(x);
 * int param_2 = obj.pop();
 * int param_3 = obj.top();
 * boolean param_4 = obj.empty();
 */
//两个Deque
class MyStack {
    Queue<Integer> que1;
    Queue<Integer> que2;

    public MyStack() {
        que1 = new ArrayDeque<>();
        que2 = new ArrayDeque<>();
    }
    
    public void push(int x) {
        que1.add(x);
    }
    
    public int pop() {
        dumpQue();
        int i = que1.remove();
        makeQue();
        return i;
    }
    
    public int top() {
        dumpQue();
        int i = que1.peek();
        makeQue();
        return i;
    }
    
    public boolean empty() {
        return que1.isEmpty() && que2.isEmpty();
    }

    private void dumpQue(){
        if(!que2.isEmpty()) return;
        while(que1.size()!=1) que2.add(que1.remove());
    }
    private void makeQue(){
        while(!que1.isEmpty()) que2.add(que1.remove());
        while(!que2.isEmpty()) que1.add(que2.remove());
    }
}

 

 优化:

1. 一个队列在模拟栈弹出元素的时,只要将队列头部的元素(除了最后一个元素外) 重新添加到队列尾部,此时再去弹出元素就是栈的顺序了。

class MyStack {
    Queue<Integer> queue;

    public MyStack() {
        queue = new LinkedList<>();
    }

    //每offer一个数进来,都重新排列,把这个数放到队列的队首
    public void push(int x) {
        queue.offer(x);
        int size = queue.size();
        while (size-- > 1)
            queue.offer(queue.poll());
    }

    public int pop() {
        return queue.poll();
    }

    public int top() {
        return queue.peek();
    }

    public boolean empty() {
        return queue.isEmpty();
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值