【Java数据结构】栈与队列 经典面试题——刷题笔记(上)

简介: 笔记

1. 实现一个最小栈

题目:


30.png


思路:


把题目要求的最小栈内部分为两个栈,一个stack用于储存所有元素,另一个min_stack用于储存最小的元素


压入第一个元素时,这个元素就是当前栈里最小元素,所以不光要压入stack栈中也要压入min_stack栈中

压入第二个元素的时候,要判断这个元素是否小于min_stack里的栈顶元素,如果小于,则将其压入min_stack

总之min_stack栈顶元素要始终保持是栈里最小的元素


删除栈顶元素的时候,除了要弹出stack里的栈顶元素

还要判断这个栈顶元素是否和min_stack栈里的栈顶元素相同,如果相同则要把min_stack栈里的栈顶元素也弹出

因为min_stack只是辅助栈,一个元素如果在储存元素的栈里都没了,辅助栈里怎么能还有呢?


获取栈顶元素就简单了,直接用java自带的方法peek()就好了,只是获取,不操作


检索最小元素就更简单了,min_stack栈是用来干嘛的?

就是用来存最小元素的嘛,直接弹出min_stack栈栈顶元素可以了

这个栈顶元素必然是整个栈里的最小元素

31.gif


实现代码

class MinStack {
    Stack<Integer> stack;
    Stack<Integer> MinStack;
    public MinStack() {//构造两个栈,一个普通栈,一个辅助栈
        stack = new Stack<>();
        MinStack = new Stack<>();
    }
    public void push(int val) {
        stack.push(val);//压入元素
        if(MinStack.isEmpty()){
            MinStack.push(val);如果两个栈都是空,也要将此元素压入辅助栈
        }
        else{
            if(val <= MinStack.peek())//如果新压入的元素小于辅助栈栈顶元素
            MinStack.push(val);//将新元素压入辅助栈
        }
    }
    public void pop() {
        //如果从普通栈中弹出的元素等于辅助栈的栈顶元素,那么也要将此元素从辅助栈弹出
        if(stack.pop().equals(MinStack.peek())){//这里要用eqauls,不能用==,pop方法和peek方法返回的是一个object类型,也就是两个对象,我们要比较对象的值,如果用==,比较的是对象的地址
            MinStack.pop();//弹出辅助栈栈顶元素
        }
    }
    public int top() {
        if(MinStack.isEmpty()){
            return -1;
        }
        return stack.peek();//查看普通栈栈顶元素
    }
    public int getMin() {
        if(MinStack.isEmpty()){
            return -1;
        }
        return MinStack.peek();//查看辅助栈栈顶元素
    }
}


2. 括号匹配问题


题目:

31.png


思路:


  1. 左括号和右括号是匹配关系,考虑用栈的方法实现
  2. 栈里只放三种左括号
  3. 遍历字符串,遇到左括号,将其入栈遇到右括号,就查看栈顶的左括号,看是否能匹配。如果能匹配上,就将此左括号出栈(删除),如果最后栈为空,那么它是有效的括号,反之不是。

32.png



实现代码

class Solution {
    public boolean isValid(String s) {
        if(s==null||s.length()==0){
            return true;
        }
        //定义一个栈,来存放左括号
        Stack stack = new Stack();
        //遍历字符串
        for(int i =0; i<s.length(); i++){
            //获取当前i小标是一个啥字符
            char ch = s.charAt(i);
            //判断当前的字符是哪个左括号,因为题上说 只有3种左括号。
            if(ch=='('||ch=='['||ch=='{'){
                stack.push(ch);
            }else{
                //进入else 说明当前i下标是一个右括号
                //但是 要判断栈空不空,有可能第一个括号就是右括号
                if(stack.empty()){
                    //说明右括号多了
                    return false;
                }
               //获取栈顶元素,只是查看是否能和读取到的括号匹配,不是出栈
               char tmp = (char)stack.peek();
               if(tmp=='('&& ch == ')'||tmp=='['&& ch == ']'||tmp=='{'&& ch == '}'){
                   //如果有可匹配的,就出栈当前的栈顶的括号
                   stack.pop();
               }else{
                   //说明括号不匹配
                   return false;
               }
            }
        }
        //字符遍历完了,判断栈是否为空
        if(stack.empty()){//如果栈最终为空,说明括号刚好都匹配上了
            return true;
        }else{//左括号多了
            return false;
        }
    }
}

3. 用队列实现栈


题目:

33.png


思路:

栈是先进后出,队列是先进先出,所以这里用两个队列来回倒,从而实现栈

抓住一个关键点,不管入栈还是出栈,都找不为空的队列进行操作

入栈时,找到不为空的队列,从队列尾部插入元素即可,就达到了入栈的效果

出栈时,找到不为空的队列,将size-1个元素加入到另一个空的队列里,然后把这个队列最后一个元素出列,就达到了出栈效果

返回栈顶元素方法与出栈类似(注意,只查看,不删除),不过要设置一个临时变量tmp储存最后出队的那个元素,而且最后出队的这个元素也要继续加入另一个队列,不然就是出栈操作了


34.gif

实现代码:

class MyStack {
    //创建两个队列
    Queue<Integer> que1;
    Queue<Integer> que2;
    public MyStack() {
        que1 = new LinkedList<>();//队列是接口,不能直接实例化
        que2 = new LinkedList<>();//队列是由链表实现的,所以要用链表来实例化队列
    }
    public void push(int x) {
        if(empty()){//一开始两个队列都是空的时候,默认将第一个元素插入到que1中
            que1.offer(x);
        }else{//从第二个元素开始,哪个队列不为空,对哪个队列进行插入操作
            if(que1.isEmpty()){
                que2.offer(x);
            }else{
                que1.offer(x);
            }
        }
    }
    public int pop() {
        if(empty()){
            return -1;
        }
      //出栈也是找哪个队列不为空,就对哪个队列进行操作
        if(que1.isEmpty()){
            int size = que2.size();
            for(int i =0 ; i<size-1 ;i++){
                int tmp = que2.poll();
                que1.offer(tmp);
            }
            return que2.poll();
        }else{
            int size = que1.size();
            for(int i =0 ; i<size-1 ;i++){
                int tmp = que1.poll();
                que2.offer(tmp);
            }
            return que1.poll();
        }
    }
    public int top() {
        if(empty()){
            return -1;
        }
     //查看栈顶元素,和出栈类似,只不过记得把队列最后一个元素继续插入到另一个队列的最后
     //不然就是出栈操作了
        if(que1.isEmpty()){
            int size = que2.size();
            int tmp = -1;
            for(int i =0 ; i<size ;i++){
                tmp = que2.poll();
                que1.offer(tmp);
            }
            return tmp;
        }else{
            int size = que1.size();
            int tmp = -1;
            for(int i =0 ; i<size ;i++){
                tmp = que1.poll();
                que2.offer(tmp);
            }
            return tmp;
        }
    }
    public boolean empty() {
        return que1.isEmpty() &&  que2.isEmpty();
    }
}



相关文章
|
11天前
|
监控 Dubbo Java
Java Dubbo 面试题
Java Dubbo相关基础面试题
|
11天前
|
SQL Java 数据库连接
Java MyBatis 面试题
Java MyBatis相关基础面试题
|
11天前
|
存储 监控 算法
Java JVM 面试题
Java JVM(虚拟机)相关基础面试题
|
11天前
|
SQL 监控 druid
Java Druid 面试题
Java Druid 连接池相关基础面试题
|
11天前
|
缓存 安全 算法
Java 多线程 面试题
Java 多线程 相关基础面试题
|
2月前
|
C语言
【数据结构】栈和队列(c语言实现)(附源码)
本文介绍了栈和队列两种数据结构。栈是一种只能在一端进行插入和删除操作的线性表,遵循“先进后出”原则;队列则在一端插入、另一端删除,遵循“先进先出”原则。文章详细讲解了栈和队列的结构定义、方法声明及实现,并提供了完整的代码示例。栈和队列在实际应用中非常广泛,如二叉树的层序遍历和快速排序的非递归实现等。
284 9
|
2月前
|
存储 算法
非递归实现后序遍历时,如何避免栈溢出?
后序遍历的递归实现和非递归实现各有优缺点,在实际应用中需要根据具体的问题需求、二叉树的特点以及性能和空间的限制等因素来选择合适的实现方式。
44 1
|
12天前
|
存储 C语言 C++
【C++数据结构——栈与队列】顺序栈的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现顺序栈的基本运算。开始你的任务吧,祝你成功!​ 相关知识 初始化栈 销毁栈 判断栈是否为空 进栈 出栈 取栈顶元素 1.初始化栈 概念:初始化栈是为栈的使用做准备,包括分配内存空间(如果是动态分配)和设置栈的初始状态。栈有顺序栈和链式栈两种常见形式。对于顺序栈,通常需要定义一个数组来存储栈元素,并设置一个变量来记录栈顶位置;对于链式栈,需要定义节点结构,包含数据域和指针域,同时初始化栈顶指针。 示例(顺序栈): 以下是一个简单的顺序栈初始化示例,假设用C语言实现,栈中存储
128 75
|
12天前
|
存储 C++ 索引
【C++数据结构——栈与队列】环形队列的基本运算(头歌实践教学平台习题)【合集】
【数据结构——栈与队列】环形队列的基本运算(头歌实践教学平台习题)【合集】初始化队列、销毁队列、判断队列是否为空、进队列、出队列等。本关任务:编写一个程序实现环形队列的基本运算。(6)出队列序列:yzopq2*(5)依次进队列元素:opq2*(6)出队列序列:bcdef。(2)依次进队列元素:abc。(5)依次进队列元素:def。(2)依次进队列元素:xyz。开始你的任务吧,祝你成功!(4)出队一个元素a。(4)出队一个元素x。
34 13
【C++数据结构——栈与队列】环形队列的基本运算(头歌实践教学平台习题)【合集】
|
12天前
|
存储 C语言 C++
【C++数据结构——栈与队列】链栈的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现链栈的基本运算。开始你的任务吧,祝你成功!​ 相关知识 初始化栈 销毁栈 判断栈是否为空 进栈 出栈 取栈顶元素 初始化栈 概念:初始化栈是为栈的使用做准备,包括分配内存空间(如果是动态分配)和设置栈的初始状态。栈有顺序栈和链式栈两种常见形式。对于顺序栈,通常需要定义一个数组来存储栈元素,并设置一个变量来记录栈顶位置;对于链式栈,需要定义节点结构,包含数据域和指针域,同时初始化栈顶指针。 示例(顺序栈): 以下是一个简单的顺序栈初始化示例,假设用C语言实现,栈中存储整数,最大
35 9

热门文章

最新文章