栈和队列面试题

news/2024/11/16 18:11:19/

文章目录

    • (1)逆波兰表达式求值
    • (2)有效的括号
    • (3)栈的压入、弹出序列
    • (4)最小栈
  • 队列
    • (1)用栈实现队列
    • (2)用队列实现栈
    • (3)设计循环队列

(1)逆波兰表达式求值

oj链接
给你一个字符串数组 tokens ,表示一个根据 逆波兰表示法 表示的算术表达式。

请你计算该表达式。返回一个表示表达式值的整数。

注意:

有效的算符为 ‘+’、‘-’、‘*’ 和 ‘/’ 。
每个操作数(运算对象)都可以是一个整数或者另一个表达式。
两个整数之间的除法总是 向零截断 。
表达式中不含除零运算。
输入是一个根据逆波兰表示法表示的算术表达式。
答案及所有中间计算结果可以用 32 位 整数表示。

class Solution {public int evalRPN(String[] tokens) {Stack<Integer> stack = new Stack<>();for(int i = 0;i < tokens.length;i++) {String str = tokens[i];if(!isOperations(str)) {//不是运算符  说明是数字,压入栈stack.push(Integer.parseInt(str));}else {//是运算符int num2 = stack.pop();int num1 = stack.pop();switch(str) {case "+":stack.push(num1+num2);break;case "-":stack.push(num1-num2);break;case "*":stack.push(num1*num2);break;case "/":stack.push(num1/num2);break;}}}return stack.pop();}/*判断当前字符串是不是一个运算符 */private boolean isOperations(String str) {return (str.equals("+") || str.equals("-") || str.equals("*") || str.equals("/"));}
}

(2)有效的括号

oj链接
给定一个只包括 ‘(’,‘)’,‘{’,‘}’,‘[’,‘]’ 的字符串 s ,判断字符串是否有效。

有效字符串需满足:

左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
每个右括号都有一个对应的相同类型的左括号。

class Solution {public boolean isValid(String s) {Stack<Character> stack = new Stack<>();//1. 遍历字符串for(int i = 0;i < s.length();i++) {char ch = s.charAt(i);//2.是不是左括号if(ch == '(' || ch == '[' || ch == '{') {stack.push(ch);}else {//3.右括号//3.1 栈为空if(stack.isEmpty()) {return false;}//3.2 栈不为空char ch2 = stack.peek();//左括号if(ch == ')' && ch2 == '('  || ch == ']'&& ch2 == '[' || ch == '}' && ch2 == '{') {stack.pop();}else {return false;}}}//字符串遍历完了 栈还是不为空return stack.isEmpty();}
}

(3)栈的压入、弹出序列

牛客网链接
输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。

  1. 0<=pushV.length == popV.length <=1000
  2. -1000<=pushV[i]<=1000
  3. pushV 的所有数字均不相同
public boolean IsPopOrder (int[] pushA, int[] popA) {Stack<Integer> stack = new Stack<>();//j是出栈的下标int j = 0;//i是入栈的下标for (int i = 0; i < pushA.length; i++) {stack.push(pushA[i]);while (!stack.empty() && j < popA.length && stack.peek() == popA[j]) {stack.pop();j++;}}//return j >= popA.length;return stack.empty();}

(4)最小栈

oj链接
设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。

实现 MinStack 类:

MinStack() 初始化堆栈对象。
void push(int val) 将元素val推入堆栈。
void pop() 删除堆栈顶部的元素。
int top() 获取堆栈顶部的元素。
int getMin() 获取堆栈中的最小元素。

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.empty()) {minStack.push(val);} else {int peekNum = minStack.peek();if(val<=peekNum) {minStack.push(val);}}}public void pop() {int val = stack.pop();if(val == minStack.peek()) {minStack.pop();}}public int top() {return stack.peek();}public int getMin() {return minStack.peek();}
}

队列

(1)用栈实现队列

oj链接
请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push、pop、peek、empty):

实现 MyQueue 类:

void push(int x) 将元素 x 推到队列的末尾
int pop() 从队列的开头移除并返回元素
int peek() 返回队列开头的元素
boolean empty() 如果队列为空,返回 true ;否则,返回 false
说明:

你 只能 使用标准的栈操作 —— 也就是只有 push to top, peek/pop from top, size, 和 is empty 操作是合法的。
你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可。

class MyQueue {private Stack<Integer> s1 ;private Stack<Integer> s2 ;public MyQueue() {s1 = new Stack<>();s2 = new Stack<>();}public void push(int x) {s1.push(x);}public int pop() {if(empty()) {return -1;}if(s2.isEmpty()) {//弹出s1当中所有的元素 放到s2中while(!s1.isEmpty()) {s2.push(s1.pop());}}return s2.pop();}public int peek() {if(empty()) {return -1;}if(s2.isEmpty()) {//弹出s1当中所有的元素 放到s2中while(!s1.isEmpty()) {s2.push(s1.pop());}}return s2.peek();}public boolean empty() {return s1.isEmpty() && s2.isEmpty();}
}

(2)用队列实现栈

oj链接
请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(push、top、pop 和 empty)。

实现 MyStack 类:

void push(int x) 将元素 x 压入栈顶。
int pop() 移除并返回栈顶元素。
int top() 返回栈顶元素。
boolean empty() 如果栈是空的,返回 true ;否则,返回 false 。

注意:

你只能使用队列的基本操作 —— 也就是 push to back、peek/pop from front、size 和 is empty 这些操作。
你所使用的语言也许不支持队列。 你可以使用 list (列表)或者 deque(双端队列)来模拟一个队列 , 只要是标准的队列操作即可。
两个队列

class MyStack {Queue<Integer> queue1;Queue<Integer> queue2;public MyStack() {queue1 = new LinkedList<Integer>();queue2 = new LinkedList<Integer>();}/** Push element x onto stack. */public void push(int x) {queue2.offer(x);while (!queue1.isEmpty()) {queue2.offer(queue1.poll());}Queue<Integer> temp = queue1;queue1 = queue2;queue2 = temp;}/** Removes the element on top of the stack and returns that element. */public int pop() {return queue1.poll();}/** Get the top element. */public int top() {return queue1.peek();}/** Returns whether the stack is empty. */public boolean empty() {return queue1.isEmpty();}
}

一个队列

class MyStack {Queue<Integer> queue;/** Initialize your data structure here. */public MyStack() {queue = new LinkedList<Integer>();}/** Push element x onto stack. */public void push(int x) {int n = queue.size();queue.offer(x);for (int i = 0; i < n; i++) {queue.offer(queue.poll());}}/** Removes the element on top of the stack and returns that element. */public int pop() {return queue.poll();}/** Get the top element. */public int top() {return queue.peek();}/** Returns whether the stack is empty. */public boolean empty() {return queue.isEmpty();}
}

(3)设计循环队列

oj链接
设计你的循环队列实现。 循环队列是一种线性数据结构,其操作表现基于 FIFO(先进先出)原则并且队尾被连接在队首之后以形成一个循环。它也被称为“环形缓冲器”。

循环队列的一个好处是我们可以利用这个队列之前用过的空间。在一个普通队列里,一旦一个队列满了,我们就不能插入下一个元素,即使在队列前面仍有空间。但是使用循环队列,我们能使用这些空间去存储新的值。

你的实现应该支持如下操作:

MyCircularQueue(k): 构造器,设置队列长度为 k 。
Front: 从队首获取元素。如果队列为空,返回 -1 。
Rear: 获取队尾元素。如果队列为空,返回 -1 。
enQueue(value): 向循环队列插入一个元素。如果成功插入则返回真。
deQueue(): 从循环队列中删除一个元素。如果成功删除则返回真。
isEmpty(): 检查循环队列是否为空。
isFull(): 检查循环队列是否已满。
数组(创建时多一个元素)
当front与rear相等的时候,不知道是为空还是为满
所以front前面的元素不用来存放,front==rear时判空,(rear+1) % elem.length == front为满

class MyCircularQueue {public int[] elem;public int front;public int rear;public MyCircularQueue(int k) {elem = new int[k+1];}//入队操作public boolean enQueue(int value) {if(isFull()) {return false;}elem[rear] = value;rear = (rear+1) % elem.length;return true;}//删除队头元素public boolean deQueue() {if(isEmpty()) {return false;}front = (front + 1) % elem.length;return true;}//得到队头元素 不删除public int Front() {if(isEmpty()) {return -1;}return elem[front];}//得到队尾元素 不删除public int Rear() {if(isEmpty()) {return -1;}int index = (rear == 0) ? elem.length-1 : rear-1;return elem[index];}//判空 front和rear相遇public boolean isEmpty() {return front == rear;}public boolean isFull() {return (rear+1) % elem.length == front;}
}

链表

class MyCircularQueue {private ListNode head;private ListNode tail;private int capacity;private int size;public MyCircularQueue(int k) {capacity = k;size = 0;}public boolean enQueue(int value) {if (isFull()) {return false;}ListNode node = new ListNode(value);if (head == null) {head = tail = node;} else {tail.next = node;tail = node;}size++;return true;}public boolean deQueue() {if (isEmpty()) {return false;}head = head.next;  size--;return true;}public int Front() {if (isEmpty()) {return -1;}return head.val;}public int Rear() {if (isEmpty()) {return -1;}return tail.val;}public boolean isEmpty() {return size == 0;}public boolean isFull() {return size == capacity;}
}

http://www.ppmy.cn/news/1263344.html

相关文章

C语言中文网C++学习笔记

目录 类也是一种构造类型&#xff0c;不但可以是变量&#xff0c;还可以是函数。解决合作开发时的命名冲突问题&#xff0c;C 引入了命名空间&#xff08;Namespace&#xff09;在C语言中&#xff0c;动态分配内存用 malloc() 函数&#xff0c;释放内存用 free() 函数。函数调用…

c语言:理解和避免野指针

野指针的定义&#xff1a; 野指针是指一个指针变量存储了一个无效的地址&#xff0c;通常是一个未初始化的指针或者指向已经被释放的内存地址。当程序尝试使用野指针时&#xff0c;可能会导致程序崩溃、内存泄漏或者其他不可预测的行为。因此&#xff0c;在编程中需要特别注意…

OpenCL不支持C++内核语言(设备语言)

在*.cl文件&#xff08;或字符串&#xff09;中不支持用class、template等&#xff01; 在*.cl文件&#xff08;或字符串&#xff09;中不支持给struct定义构造函数或成员函数&#xff01; 在*.cl文件&#xff08;或字符串&#xff09;中不支持函数默认参数&#xff0c;例如&…

java-自动生成数据库设计文档

目录 screw 官网介绍 screw 的特点&#xff1a; 目前支持的数据库有&#xff1a; 文档生成支持&#xff1a; 文档截图 html word 引入jar 生产代码 screw 官网介绍 https://gitee.com/leshalv/screw#https://gitee.com/link?targethttps://my.oschina.net/mdxlcj/b…

【wpf】handycontrol growl 打造一个比弹窗优雅10倍的信息通知方式

前言 话不多说&#xff0c;先上图&#xff1a; 这种弹框不会影响主进程的脚本&#xff0c;同时分为四个等级&#xff1a; 普通消息&#xff1a;Info &#xff08;时间一到&#xff0c;自动消失&#xff0c;除非鼠标停留上面&#xff09;警告&#xff1a; Warning &#xff0…

用stl写一个自动打分比赛的案例

我们要实现六名选手进行随机平均分为两组&#xff0c;先分别淘汰两组中的最后一名&#xff0c; 再决出第一名。 抽象选手 class player { public:string name;int score; }; 一个选手有名字和分数 首先我们需要vector容器保存选手的编号&#xff0c;便于后续的操作。 再用…

【Java】构建表达式二叉树和表达式二叉树求值

问题背景 1. 实现一个简单的计算器。通过键盘输入一个包含圆括号、加减乘除等符号组成的算术表达式字符串&#xff0c;输出该算术表达式的值。要求&#xff1a; &#xff08;1&#xff09;系统至少能实现加、减、乘、除等运算&#xff1b; &#xff08;2&#xff09;利用二叉…

【面试常考题目】五种方法解决“如何在n个无序数组中找出它的中位数(java)”问题

1.3 从N个数组中找到中位数&#xff0c;每一个数组可能乱序 在LeetCode上&#xff0c;"寻找多个数组的中位数"这类问题通常是由两个数组合并中位数问题&#xff08;即LeetCode第4题&#xff09;的变种或扩展。直接对应于多个数组合并后寻找中位数的题目在LeetCode上…