栈和队列常见题型(java版)

直接上干货。。。。。

栈和队列常见题型:

  1. 实现栈和实现队列。
  2. 两个栈实现一个队列。
  3. 设计栈,使得pop,push和min时间复杂度为O(1)。
  4. 滑动窗口的最大值。
  5. 栈的进出序列。

实现栈和实现队列

主要包括:栈,队列,循环队列。


package com.sywyg;

/**
 * 实现栈
 * 数组应该是Object类型的
 * 注意top的设置影响出栈和获取栈顶元素。
 * size也可以用top代替
 */
class MyStack<E>{
    // 栈元素个数
    private int size;
    // 栈头
    private int top;
    // 数组保存元素
    private Object[] stack = null;
    public MyStack(int length){
        stack = new Object[length];
        top = 0;
    }
    public int size(){
        return size;
    }
    // 进栈
    public void push(E e){
        if(size == stack.length){
            try{
                throw new Exception("栈已满");
            }catch(Exception ex){
                ex.printStackTrace();
            }
        }
        stack[top++] = e;
        size++;
    }
    // 出栈
    public E pop(){
        E e = null;
        if(size == 0){
            try{
                throw new Exception("栈为空");
            }catch(Exception ex){
                ex.printStackTrace();
            }
        }
        e = (E)stack[--top];
        size--;
        return e;
    }
    // 获取栈顶元素
    public E top(){
        if(size == 0){
            try{
                throw new Exception("栈为空");
            }catch(Exception e){
                e.printStackTrace();
            }
        }
        return (E)stack[top-1];
    }
}

/**
 * 创建队列,这种队列会造成假溢出
 */
class MyQueue<E>{
    // 队列长度
    private int size;
    // 队头
    private int front;
    // 队尾
    private int back;
    private Object[] queue;
    public MyQueue(int length){
        queue = new Object[length];
        size = 0;
        front = 0;
        back = 0;
    }

    public int size(){
        return size;
    }
    // 进队
    public void enqueue(E e){
        if(size == queue.length){
            try{
                throw new Exception("队已满");
            }catch(Exception ex){
                ex.printStackTrace();
            }
        }
            queue[back++] = e;
            size++;
    }
    // 出队
    public E dequeue(){
        E e = null;
        if(size == 0 || back == front){
            try{
                throw new Exception("队为空");
            }catch(Exception ex){
                ex.printStackTrace();
            }
        }
        e = (E)queue[front++];
        size--;
        return e;
    }
    // 返回队头
    public E front(){
        return (E)queue[front];
    }
    // 返回队尾?
    public E back(){
        return (E)queue[back - 1];
    }
}

/**
 * 循环队列,采用浪费一个位置(使用size可以保证全利用)
 * 这里不使用size标记队列的长度,尽管这种方式很简单
 */
class LoopQueue<E>{
    // 队头
    private int front;
    // 队尾
    private int back;
    private Object[] queue;
    public LoopQueue(int length){
        // 浪费一个
        queue = new Object[length + 1];
        front = 0;
        back = 0;
    }

    public int size(){
        return (back - front + queue.length)% queue.length;
    }
    // 进队
    public void enqueue(E e){
        if((front - back + queue.length)% queue.length == 1){
            try{
                throw new Exception("队已满");
            }catch(Exception ex){
                ex.printStackTrace();
            }
        }
        queue[back ++ % queue.length] = e;

    }
    // 出队
    public E dequeue(){
        E e = null;
         if(front == back){
            try{
                throw new Exception("队为空");
            }catch(Exception ex){
                ex.printStackTrace();
            }
         }
            e = (E)queue[front++ % queue.length];
        return e;
    }
    // 返回队头
    public E front(){
        return  (E)queue[front];
    }
    // 返回队尾?
    public E back(){
        return  (E)queue[(back - 1 + queue.length) % queue.length];
    }
}

两个栈实现一个队列

思想:一个栈A只进,一个栈B只出,B为空则A元素进入B,再出栈。


package com.sywyg;

/**
 * 两个栈实现一个队列。
 * 这样仍然会造成假溢出。
 *
 *
 */
    public static class Solution<E>{
        // 应该在构造器中赋值。
        // stack1用来入队
        private Stack<E> stack1 = new Stack<E>();
        // stack2用来出队
        private Stack<E> stack2 = new Stack<E>();

        // 入队
        public void enqueue(E e){
            stack1.push(e);
            //System.out.println("此时stack1栈顶元素为:" + stack1.top());
        }

        // 出队
        public E dequeue(){
            E e = null;
            if(stack2.size() != 0){
                e = stack2.pop();
            }else if(stack1.size() != 0){
                int length = stack1.size();
                for(int i = 0;i<length;i++){
                    stack2.push(stack1.pop());
                    //System.out.println("此时stack2栈顶元素为:" + stack2.top());
                }
                e = stack2.pop();
            }
            return e;
        }
}

- 测试:进进出出,进出。
- 如何用两个队列实现一个栈。

#设计栈,使得pop,push和min时间复杂度为O(1)

思想:额外的栈A存放当前最小值,每当进来的值a小于/等于该栈顶值b时,a需要入栈A;出栈时若栈A的栈顶和刚出栈的元素相等时,则A也出栈。

```java

package com.sywyg;
import java.util.Stack;

/**
 * 设计栈,使得pop,push和min时间复杂度为O(1)。
 * 或者使用一个每个最小值再包含一个计数标记
 */
    public static class Solution<E>{
        private Stack<E> stack,stackMin;
        public Solution(){
            stack = new Stack<E>();
            stackMin = new Stack<E>();
        }
        // 入栈
        public void push(E e){
            stack.push(e);
            if(stackMin.isEmpty()){
                stackMin.push(e);
            }else if(stackMin.peek() >= e){
                stackMin.push(e);
            }
        }
        // 出栈
        public E pop(){
            E e = stack.pop();
            if(e == stackMin.peek()){
                stackMin.pop();
            }

        }
        // 返回最小
        public E min(){
            return stackMin.peek();
        }
}

<div class="se-preview-section-delimiter"></div>
  • 测试:小大大大小小,每次出栈判断是否正确。
  • 时间复杂度:O(1),空间复杂度O(n)

滑动窗口的最大值

给定一个数组,和滑动窗口的大小,计算每个窗口中的最大值。例如数组{1,2,3,4,5},窗口大小为3。那么共存在3个滑动窗口,它们的大小为:{3,4,5}。

思想:须用到上面的第2题和第3题,用两个能够O(1)时间内计算出最大值的栈实现队列。先进入3个(窗口大小),然后再依次进1出1个。在统计最大值的时候比较两个栈中的最大值即可,注意需要判断栈是否为空。


package com.sywyg;

import java.util.Stack;

/**
 * 滑动窗口的最大值。
 * @author sywyg
 * 测试
 */
public class Question4 {

    public static void main(String[] args) {
        int[] array = {2,3,4,2,6,5,2,1};
        int[] max = solution(array, 3);
        for (int i = 0; i < max.length; i++) {
            System.out.println(max[i]);
        }
    }

    public static int[] solution(int[] array,int size){
        int[] max = new int[array.length - size + 1];
        MyQueue<Integer> queue = new MyQueue<Integer>();
        int i = 0;
        for(i = 0; i<size; i++){
            queue.enqueue(array[i]);
        }
        int j = 0;
        // 先进一个
        max[j++] = queue.stack1.max();
        for(;i<array.length;i++){
            queue.dequeue();
            queue.enqueue(array[i]);
            // 两个栈中的最大值进行比较
            if(queue.stack2.stackMax.size() == 0 || queue.stack1.max() >= queue.stack2.max()){
                max[j++] = queue.stack1.max();
            }else
                max[j++] = queue.stack2.max();
        }
        return max;
    }

    /**
     * 两个栈实现队列
     */
    public static class MyQueue<E>{
        // 应该在构造器中赋值。
        // stack1用来入队
        public MyStack<E> stack1 = new MyStack<E>();
        // stack2用来出队
        public MyStack<E> stack2 = new MyStack<E>();

        // 入队
        public void enqueue(E e){
            stack1.push(e);
            //System.out.println("此时stack1栈顶元素为:" + stack1.top());
        }

        // 出队
        public E dequeue(){
            E e = null;
            if(stack2.size() != 0){
                e = stack2.pop();
            }else if(stack1.size() != 0){
                int length = stack1.size();
                for(int i = 0;i<length;i++){
                    stack2.push(stack1.pop());
                    //System.out.println("此时stack2栈顶元素为:" + stack2.top());
                }
                e = stack2.pop();
            }
            return e;
        }
    }
    /**
     * pop(),push(),max() 复杂度为O(1)
     */
    public static class MyStack<E>{
        public Stack<E> stack,stackMax;
        public MyStack(){
            stack = new Stack<E>();
            stackMax = new Stack<E>();
        }
        // 入栈
        public void push(E e){
            stack.push(e);
            if(stackMax.isEmpty()){
                stackMax.push(e);
            }else if((Integer)stackMax.peek() <= (Integer)e){
                stackMax.push(e);
            }
        }
        // 出栈
        public E pop(){
            E e = stack.pop();
            if(e == stackMax.peek()){
                stackMax.pop();
            }
            return e;
        }
        // 返回最大
        public E max(){
            return stackMax.peek();
        }

        public E peek(){

            return stack.peek();
        }
        public int size(){
            return stack.size();
        }
    }

}

<div class="se-preview-section-delimiter"></div>
  • 测试:有大有小的输入。
  • 时间复杂度:O(n)

栈的进出序列

输入进栈的顺序判断给出的出栈顺序是否正确。

思想:先进栈,然后判断是否和给出的顺序相等。若不相等则继续进栈判断,直到进完;若相等则继续出栈判断,直到出完。


package com.sywyg;

import java.util.Stack;

/**
 * 栈的进出序列
 * @author sywyg
 * @since 2015.7.25
 * 测试:
 */
public class Question5 {

    public static void main(String[] args) {
        Question5 question = new Question5();
        int[] array1 = {1,2,3,4,7};
        int[] array2 = {3,1,2,5,0};
        System.out.println(question.solution(array1, array2));
    }

    // 第一个参数为输入顺序,第二个参数为要判断的输出结果
    public boolean solution(int[] array1,int[] array2){
        // 健壮性判断
        if(array1 == null || array2 == null) return false;
        if(array1.length != array2.length) return false;

        Stack<Integer> stack = new Stack<Integer>();
        int i = 0,j = 0;
        for (; i < array1.length; i++) {
            stack.push(array1[i]);
            while(stack.size() != 0 && stack.peek() == array2[j]) {
                stack.pop();
                j++;
            }
        }
        return j == i?true:false;
    }

}
  • 测试:给出正确的,给出错误的,给出不相等的数组。
  • 时间复杂度:O(n)

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-11 09:15:28

栈和队列常见题型(java版)的相关文章

java 栈和队列的模拟--java

栈的定义:栈是一种特殊的表这种表只在表头进行插入和删除操作.因此,表头对于栈来说具有特殊的意义,称为栈顶.相应地,表尾称为栈底.不含任何元素的栈称为空栈. 栈的逻辑结构:假设一个栈S中的元素为an,an-1,..,a1,则称a1为栈底元素,an为栈顶元 素.栈中的元素按a1 ,a2,..,an-1,an的次序进栈.在任何时候,出栈的元素都是栈顶元素.换句话说,栈的修改是按后进先出的原则进行的.因此,栈又称为后进先出(Last In First Out)表,简称为LIFO表.所以,只要问题满足LI

数据结构之栈和队列及其Java实现

栈和队列是数据结构中非常常见又非常基础的线性表,在某些场合栈和队列使用很多,因此本篇主要介绍栈和队列,并用Java实现基本的栈和队列,同时用两个栈实现队列和用两个队列实现栈. 栈:栈是一种基于"后进先出"策略的线性表.在插入时(入栈),最先插入的元素在栈尾,最后插入的元素在栈顶:在删除时(出栈),最后插入的元素先出栈,最先插入的元素最后出栈.由此可见,对栈的插入和删除操作都是在栈顶位置进行的. 在Java中,提供了一个类Stack<E>来实现栈的这些特性,并提供了一些常用的

栈和队列的常见题型

一.常见题型如下: 1. 实现一个栈,要求实现Push(出栈).Pop(入栈).Min(返回最小值的操作)的时间复杂度为O(1) 2. 使用两个栈实现一个队列 3. 使用两个队列实现一个栈 4. 元素出栈.入栈顺序的合法性.如入栈的序列(1,2,3,4,5),出栈序列为(4,5,3,2,1) 5. 一个数组实现两个栈. 二.解法分析及示例代码 1.第一题前两种操作Push(出栈).Pop(入栈)比较好实现,也是栈中比较基本的操作,题目没有明确要求所以我们可以直接用STL容器,进行个封装即可,st

链表常见题型(java版)

直接上干货..... 链表常见题型: 找到单链表的倒数第k个节点. 删除单链表中的某个结点(O(1)). 反转链表. 两个链表的第一个公共结点. 有环链表返回环路的开头节点(及判断是否有环). 合并两个排序的链表. 删除链表中重复的结点. 先给出链表的定义: /** * 单链表定义 */ public static class Node<E>{ private E element;//节点保存的元素 private Node<E> next;//指向下一个节点的引用 public

3-5-表达式求值-栈和队列-第3章-《数据结构》课本源码-严蔚敏吴伟民版

课本源码部分 第3章  栈和队列 - 表达式求值 ——<数据结构>-严蔚敏.吴伟民版        源码使用说明  链接??? <数据结构-C语言版>(严蔚敏,吴伟民版)课本源码+习题集解析使用说明        课本源码合辑  链接??? <数据结构>课本源码合辑        习题集全解析  链接??? <数据结构题集>习题解析合辑        本源码引入的文件  链接? SequenceStack.c        相关测试数据下载  链接? 无数据

3-6-汉诺塔(Hanoi Tower)问题-栈和队列-第3章-《数据结构》课本源码-严蔚敏吴伟民版

课本源码部分 第3章  栈和队列 - 汉诺塔(Hanoi Tower)问题 ——<数据结构>-严蔚敏.吴伟民版        源码使用说明  链接??? <数据结构-C语言版>(严蔚敏,吴伟民版)课本源码+习题集解析使用说明        课本源码合辑  链接??? <数据结构>课本源码合辑        习题集全解析  链接??? <数据结构题集>习题解析合辑        本源码引入的文件  链接? 无外链        相关测试数据下载  链接? 无数

用JS描述的数据结构及算法表示——栈和队列(基础版)

前言:找了上课时数据结构的教程来看,但是用的语言是c++,所以具体实现在网上搜大神的博客来看,我看到的大神们的博客都写得特别好,不止讲了最基本的思想和算法实现,更多的是侧重于实例运用,一边看一边在心里隐隐歌颂大神的厉害,然后别人的厉害不是我的,所以到底看得各种受打击+头昏脑涨,写这个系列是希望自己能够总结学到东一块.西一下的知识,因为水平有限+经验不足,所以在此只说最基础的思想,附上我自己的算法实现(肯定还有更优解),如果要想看进阶版的,可以在园里搜“数据结构”,各种语言实现和进阶提升的文章有很

3-3-行编辑程序-栈和队列-第3章-《数据结构》课本源码-严蔚敏吴伟民版

课本源码部分 第3章  栈和队列 - 行编辑程序 ——<数据结构>-严蔚敏.吴伟民版        源码使用说明  链接??? <数据结构-C语言版>(严蔚敏,吴伟民版)课本源码+习题集解析使用说明        课本源码合辑  链接??? <数据结构>课本源码合辑        习题集全解析  链接??? <数据结构题集>习题解析合辑        本源码引入的文件  链接? SequenceStack.c        相关测试数据下载  链接? 无数据

3-9-模拟银行排队过程-栈和队列-第3章-《数据结构》课本源码-严蔚敏吴伟民版

课本源码部分 第3章  栈和队列 - 模拟银行排队过程 ——<数据结构>-严蔚敏.吴伟民版        源码使用说明  链接??? <数据结构-C语言版>(严蔚敏,吴伟民版)课本源码+习题集解析使用说明        课本源码合辑  链接??? <数据结构>课本源码合辑        习题集全解析  链接??? <数据结构题集>习题解析合辑        本源码引入的文件  链接? Status.h.SinglyLinkedList.c.LinkQueue