算法打卡day9|栈与队列篇01|Leetcode 232.用栈实现队列、225. 用队列实现栈

目录

栈与队列理论基础

栈(Stack)

队列(Queue)

栈与队列的使用场景

算法题

Leetcode  232.用栈实现队列

个人思路

解法

Leetcode 225. 用队列实现栈

个人思路

解法


栈与队列理论基础

栈(Stack)


栈是一种后进先出(LIFO)的数据结构,即最近添加到栈中的元素将是第一个被移除的元素。

栈通常有两个主要的操作:push 用于添加一个元素到栈顶,而 pop 用于移除栈顶的元素。此外,还有一个 peek 操作,它允许查看栈顶元素而不移除它。

在Java中,Stack 类是一个继承自 Vector 的类,提供了栈的实现。但是,由于 Vector 是同步的,这可能导致不必要的性能开销,因此在单线程应用程序中,更推荐使用 ArrayDeque 类,它实现了 Deque 接口并提供了一个更高效的栈实现

队列(Queue)


队列是一种先进先出(FIFO)的数据结构,即最先添加到队列中的元素将是第一个被移除的元素。

队列的基本操作包括 enqueue(添加元素到队列尾部)和 dequeue(移除队列头部的元素)。与栈类似,还有一个 peek 操作,用于查看队列头部的元素而不移除它。

Java中,LinkedList 类可以作为队列使用,因为它实现了 List 接口,而 List 接口又扩展了 Queue 接口。但是,LinkedList 不是专门为队列操作优化的。对于需要高性能队列的场景,可以使用 ArrayDeque ,它同样实现了 Deque 接口,并且提供了队列的高效实现

栈与队列的使用场景

  • :适用于需要后进先出特性的场合,例如函数调用栈(每次调用新函数时将其推入栈,返回时弹出栈),表达式求值(如后缀表达式的计算),以及深度优先搜索(DFS)等。
  • 队列:适用于需要先进先出特性的场合,例如任务调度(按顺序处理任务),广度优先搜索(BFS),以及实现生产者-消费者问题等。

栈和队列的物理与逻辑存储结构


物理存储结构指的是数据在计算机内存中实际的存储方式,而逻辑存储结构描述的是数据元素之间的抽象关系。

  • 数组是一种顺序存储结构,数据在内存中连续存放。
  • 链表是一种链式存储结构,数据在内存中可能分散存放,每个元素通过指针连接。

栈和队列都可以通过数组和链表来实现,具体选择哪种物理存储结构取决于具体的应用场景和性能需求。例如,对于栈,如果我们知道栈的大小不会变化太多,可以使用数组实现;如果栈大小经常变化,使用链表可能更加合适。对于队列,如果队列操作频繁,且队列大小固定,可以使用循环数组实现;如果队列大小可变,使用链表实现可能更加高效。

算法题

Leetcode  232.用栈实现队列

题目链接:232.用栈实现队列

大佬视频讲解:用栈实现队列视频讲解

个人思路

需要两个栈一个输入栈,一个输出栈;push数据的时候,数据直接放进输入栈就好;但在pop的时候,操作就复杂一些,输出栈如果为空,就把进栈数据全部导入进来再从出栈弹出数据,如果输出栈不为空,则直接从出栈弹出数据就可以了。

解法
class MyQueue {

    Stack<Integer> stackIn;//输入栈
    Stack<Integer> stackOut;//输出栈

    public MyQueue() {
        stackIn = new Stack<>(); // 负责进栈
        stackOut = new Stack<>(); // 负责出栈
    }
    
    public void push(int x) {//插入数据
        stackIn.push(x);
    }
    
    public int pop() { //弹出数据   
        dumpstackIn();//1.先将输入栈全部弹出到输出栈
        return stackOut.pop();//2.再弹出输出栈数据
    }
    
    public int peek() {//获取一个输入的数据
        dumpstackIn();//1.先将输入栈全部弹出到输出栈
        return stackOut.peek();//2.输出栈的第一个数据 就是队列的第一个数据
    }
    
    public boolean empty() {//判空
        return stackIn.isEmpty() && stackOut.isEmpty();
    }

// 如果stackOut为空,那么将stackIn中的元素全部放到stackOut中
    private void dumpstackIn(){    
        if (!stackOut.isEmpty()) return; 
        while (!stackIn.isEmpty()){
                stackOut.push(stackIn.pop());//将输入栈全部弹出到输出栈
        }
    }
}
 

时间复杂度:O(n);(push和empty为O(1), pop和peek为O(n)

空间复杂度:O(n);(2个辅助栈)

Leetcode 225. 用队列实现栈

题目链接:225. 用队列实现栈

大佬视频讲解:225. 用队列实现栈

个人思路

也是需要用两个队列que1和que2实现栈的功能其中que2其实完全就是一个数据备份的作用.在实现栈的push功能时,先将push 的元素放进que2,再看que1中有没有其他元素,有就把元素输出放入que2,再将que2变成que1, 这样que1弹出元素的顺序和原来栈完全一样了;

举个例子

队列1中现在有一个元素1, 需要放入4, 先将4放入队列2备份,再将1弹出放入队列2,这样队列2就变成了1,4 再将队列2和队列1交换,这样队列1的顺序就和栈的顺序一样了; 这样后续实现栈的弹出就直接弹出即可

解法

class MyStack {

    Queue<Integer> queue1; // 和栈中保持一样元素的队列
    Queue<Integer> queue2; // 备份队列

    public MyStack() {
        queue1 = new LinkedList<>();
        queue2 = new LinkedList<>();
    }
    
    public void push(int x) {
        queue2.offer(x); // 先放在备份队列中
        while (!queue1.isEmpty()){
            queue2.offer(queue1.poll());//将队列1的元素全部弹出放入队列2
        }

        Queue<Integer> queueTemp;
        queueTemp = queue1;
        queue1 = queue2;
        queue2 = queueTemp; // 最后交换队列1和队列2,将元素都放到队列1中
    }
    
    public int pop() {
        return queue1.poll(); // 因为queue1中的元素和栈中的保持一致,所以这个和下面两个的操作只看queue1即可
    }
    
    public int top() {
        return queue1.peek();
    }
    
    public boolean empty() {
        return queue1.isEmpty();
    }
}

时间复杂度:O(n);(pop为O(n),其他为O(1))

空间复杂度:O(n);(两个队列)

还可以优化到一个队列实现

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

class MyStack {
    Queue<Integer> queue;
    
    public MyStack() {
        queue = new LinkedList<>();
    }
    
    public void push(int x) {
        queue.add(x);
    }
    
    public int pop() {
        rePosition();
        return queue.poll();
    }
    
    public int top() {
        rePosition();
        int result = queue.poll();
        queue.add(result);
        return result;
    }
    
    public boolean empty() {
        return queue.isEmpty();
    }

    public void rePosition(){//将队头元素移到队尾 除了最后一个元素
        int size = queue.size();
        size--;
        while(size-->0)
            queue.add(queue.poll());
    }
}

时间复杂度:O(n);(top,pop为O(n),其他为O(1))

空间复杂度:O(n);(两个队列)

以上是个人的思考反思与总结,若只想根据系列题刷,参考卡哥的网址代码随想录算法官网

  • 29
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值