Java 栈与队列实战真题训练

 更新时间:2022年04月02日 08:48:06   作者:Pretend..  
在编写程序的时候,对于栈与队列的应用需要熟练的掌握,这样才能够确保写出来的代码有质量。本文小编就以几个题目详细说说Java中的栈与队列,需要的朋友可以参考一下

1、实现循环队列

【OJ链接】

循环队列一般通过数组实现。我们需要解决几个问题。

(1)数组下标实现循环

a、下标最后再往后(offset 小于 array.length): index = (index + offset) % array.length。通俗一点,就是如果我们的数组大小为8,下标走到了7,再往后如何回到0,我们可以(index+1)%8来实现。

b、下标最前再往前的时候,我们特殊判断一下,将其置为数组大小减一即可。

(2)区分队列的满与空

我们可以给数组预留一个位置,如果rear+1=front,则表示队列已满;如果rear=front,表示队列为空。这个情况下,我们需要考虑队列大小的问题,在定义数组大小时,需要比原有的大一。

 【代码如下】

class MyCircularQueue {
    public int front;
    public int rear;
    public int[] array;
 
    //构造方法
    public MyCircularQueue(int k) {
       //因为预留位置的缘故,数组的大小要定义为k+1
       this.array=new int[k+1];
    }
    //入队
    public boolean enQueue(int value) {
        if(isFull()){
            return false;
        }
        this.array[this.rear]=value;
        this.rear=(this.rear+1)%this.array.length;
        return true;
    }
    //出队
    public boolean deQueue() {
        if(isEmpty()){
            return false;
        }
        this.front=(this.front+1)%this.array.length;
        return true;
    }
    //获取队头
    public int Front() {
        if(isEmpty()){
            return -1;
        }
        return this.array[front];
    }
    //获取队尾
    public int Rear() {
        if(isEmpty()){
            return -1;
        }
        int index=-1;
        if(this.rear==0){
            index=this.array.length-1;
        }else{
            index=this.rear-1;
        }
        return this.array[index];
    }
    //判断是否为空
    public boolean isEmpty() {
        if(this.front==this.rear){
            return true;
        }
        return false;
    }
    //判断队列是否满
    public boolean isFull() {
        if((this.rear+1)%this.array.length==this.front){
            return true;
        }
        return false;
    }
}

2、队列实现栈

【OJ链接】

因为栈的先进后出、队列的先进先出原则。我们需要两个队列来实现栈。当两个队列都为空时,栈为空。

  • 入栈(push):第一次入栈无所谓,两个队列都为空,随便选择一个队列入队即可;后面入栈时,肯定会有一个队列不为空,找到不为空的队列,进行入队操作。
  • 出栈(pop):首先栈为空时,不能进行出栈操作;栈不为空时,肯定有一个队列为空(queue1),一个队列不为空(queue2),将queue1中的size-1个元素出栈到queue2中(特别注意不能将求queue1大小的函数放进循环里,queue进行出队操作时,其大小是改变的),最后将queue1中最后一个元素进行出队最为返回值。
  • 获取栈顶元素(top):和出栈差不多,就不细说了

【代码如下】

class MyStack {
    private Queue<Integer> queue1;
    private Queue<Integer> queue2;
 
    //构造方法
    public MyStack() {
        queue1=new LinkedList<>();
        queue2=new LinkedList<>();
    }
    //入栈
    public void push(int x) {
        if(!queue2.isEmpty()){
            queue2.offer(x);
        }else{
            queue1.offer(x);
        }
    }
    //出栈
    public int pop() {
        if(empty()){
            return -1;
        }
        if(queue1.isEmpty()){
            int size=queue2.size();
            for(int i=0;i<size-1;++i){
                int x=queue2.poll();
                queue1.offer(x);
            }
            return queue2.poll();
        }else{
            int size=queue1.size();
            for(int i=0;i<size-1;++i){
                int x=queue1.poll();
                queue2.offer(x);
            }
            return queue1.poll();
        }
    }
    //获取栈顶元素
    public int top() {
        if(empty()){
            return -1;
        }
        if(queue1.isEmpty()){
            int x=-1;
            int size=queue2.size();
            for(int i=0;i<size;++i){
                x=queue2.poll();
                queue1.offer(x);
            }
           return x;
        }else{
            int size=queue1.size();
            int x=-1;
            for(int i=0;i<size;++i){
                x=queue1.poll();
                queue2.offer(x);
            }
            return x;
        }
    }
    //判断栈是否为空
    public boolean empty() {
        if(queue1.isEmpty()&&queue2.isEmpty()){
            return true;
        }
        return false;
    }
}

3、栈实现队列

【OJ链接】

还是和上面一样,需要用到两个栈(stack1、stack2)。和实现栈列不同的是,入队只能对同一个栈进行操作。如果两个栈都为空,则队列为空。

  • 入队(push):规定stack1用来入队。每次入队时,对stack1进行入栈操作即可。
  • 出队(pop):规定stack2进行出队操作。如果队列为空时,不能进行出队操作。当stack2为空时,我们需要将stack1中所有元素出栈,放入stack2中,然后对stack2进行出栈操作。如果stack2不为空,则直接对stack2进行出栈操作即可。
  • 获取队列开头元素(peek):和出栈操作相同,最后只需要获取stack2的栈顶元素即可。

【代码如下】

class MyQueue {
    private Stack<Integer> stack1;
    private Stack<Integer> stack2;
    //构造方法
    public MyQueue() {
        stack1=new Stack<>();
        stack2=new Stack<>();
    }
    //入队操作
    public void push(int x) {
        stack1.push(x);
    }
    //出队操作
    public int pop() {
        if(stack2.empty()){
            int size=stack1.size();
            for(int i=0;i<size;++i){
                int x=stack1.pop();
                stack2.push(x);
            }
        }
        return stack2.pop();
 
    }
    //获取队列开头的元素
    public int peek() {
        if(stack2.empty()){
            int size=stack1.size();
            for(int i=0;i<size;++i){
                int x=stack1.pop();
                stack2.push(x);
            }
        }
        return stack2.peek();
    }
    //判断队列是否为空
    public boolean empty() {
        if(stack1.empty()&&stack2.empty()){
            return true;
        }
        return false;
    }
}

4、实现最小栈

【OJ链接】

其实就是要在O(1)的时间复杂度内找到栈的最小元素。需要两个栈来实现,一个栈来进行出栈、入栈操作。只需要保证不管如何操作,另一个栈的栈顶元素都是当前栈的最小元素即可。

两个栈stack1、stack2,站的操作都在stack1中:

  • 入栈:如果第一次入栈,我们需要将其也放入stack2中,之后的入栈,将入栈元素与stack2的栈顶元素进行比较,如果其小于stack2的栈顶元素,则将其放入stack2中。
  • 出栈:对stack1出栈时,将其与stack2的栈顶元素进行比较,如果其等于stack2的栈顶元素,则对stack2进行出栈操作。

这样就能保证stack2的栈顶元素总是stack1的最小元素。注意:如果stack1中入栈两个相同的最小元素,都需要对stack2进行入栈。

【代码如下】

class MinStack {
    private Stack<Integer> stack1;
    private Stack<Integer> stack2;
    //构造方法
    public MinStack() {
        stack1=new Stack<>();
        stack2=new Stack<>();
    }
    //入栈
    public void push(int val) {
        stack1.push(val);
        if(stack2.empty()){
            stack2.push(val);
        }else{
            if(val<=stack2.peek()){
                stack2.push(val);
            }
        }
    }
    //出栈
    public void pop() {
        int x=stack1.pop();
        if(x==stack2.peek()){
            stack2.pop();
        }
    }
    //获取栈顶元素
    public int top() {
        return stack1.peek();
    }
    //获取栈的最小元素
    public int getMin() {
        return stack2.peek();
    }
}

到此这篇关于Java 栈与队列实战真题训练的文章就介绍到这了,更多相关Java 栈与队列内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java中日期时间的用法总结

    Java中日期时间的用法总结

    在日常开发中,我们经常需要处理日期和时间,所以这篇文章小编为大家总结了下 Java 中日期与时间的基本概念与一些常用的用法,希望对大家有所帮助
    2023-09-09
  • Java异常处理操作实例小结

    Java异常处理操作实例小结

    这篇文章主要介绍了Java异常处理操作,结合实例形式总结分析了java异常处理常见操作情况与相关处理技巧,需要的朋友可以参考下
    2019-07-07
  • Java中的三种代理模式详解

    Java中的三种代理模式详解

    这篇文章主要介绍了Java中的三种代理模式详解,代理模式的关键点是:代理对象与目标对象.代理对象是对目标对象的扩展,并会调用目标对象,文中提供了部分代码,需要的朋友可以参考下
    2023-08-08
  • Spring boot实现一个简单的ioc(2)

    Spring boot实现一个简单的ioc(2)

    这篇文章主要为大家详细介绍了Spring boot实现一个简单ioc的第二篇,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-04-04
  • SpringBoot拦截器的使用介绍

    SpringBoot拦截器的使用介绍

    大家好,本篇文章主要讲的是SpringBoot拦截器的使用介绍,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下
    2022-01-01
  • JavaWeb 简单分页实现代码

    JavaWeb 简单分页实现代码

    这篇文章主要介绍了JavaWeb 简单分页实现代码的相关资料,需要的朋友可以参考下
    2016-11-11
  • SpringBoot SSMP 整合案例分享

    SpringBoot SSMP 整合案例分享

    这篇文章主要介绍了SpringBoot SSMP 整合案例分享,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的小伙伴可以参考一下
    2022-08-08
  • JVM中判定对象需要回收的方法

    JVM中判定对象需要回收的方法

    这篇文章主要介绍了jvm中如何判定对象需要回收,jvm在确定是否回收的对象的时候采用的是root搜索算法来实现,需要的朋友可以参考下
    2022-04-04
  • 解决SpringBoot在后台接收前台传递对象方式的问题

    解决SpringBoot在后台接收前台传递对象方式的问题

    这篇文章主要介绍了解决SpringBoot在后台接收前台传递对象方式的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-01-01
  • Java中synchronized用法汇总

    Java中synchronized用法汇总

    使用 synchronized 无需手动执行加锁和释放锁的操作,我们只需要声明 synchronized 关键字就可以了,JVM 层面会帮我们自动的进行加锁和释放锁的操作,我们今天重点来看一下synchronized 的几种用法
    2022-04-04

最新评论