文章目录
232.用栈实现队列
题目大意
请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push、pop、peek、empty):
实现 MyQueue 类:
- void push(int x) 将元素 x 推到队列的末尾
- int pop() 从队列的开头移除并返回元素
- int peek()返回队列开头的元素
- boolean empty() 如果队列为空,返回 true ;否则,返回 false
解题思路
栈的顺序为后进先出,而队列的顺序是先进先出。使用两个栈实现队列,一个元素需要经过两个栈才能出队列,在经过第一个栈时元素顺序被反转,经过第二个栈时再次被反转,此时就是先进先出顺序。
时间复杂度:push
和Empty
为O(1),pop
和peek
为均摊O(1)。对于每个元素,至多入栈和出栈各两次,故均摊复杂度为O(1)。
空间复杂度:O(n)。其中n是操作总数,对于有n次push
操作的情况,队列会有n个元素,故空间复杂度为O(n)。
栈的相关操作:
- 栈的定义:
Stack<Integer> stack=new Stack<>();
- 添加元素:
stack,push();
- 元素出栈:
stack.pop();
- 获取栈顶元素:
stack.peek();
- 判断栈是否为空:
stack.isEmpty();
代码实现
class MyQueue {
//定义两个栈
Stack<Integer> in=new Stack<>();
Stack<Integer> out=new Stack<>();
/** Initialize your data structure here. */
public MyQueue() {
}
/** Push element x to the back of queue. */
public void push(int x) {
in.push(x);
}
/** Removes the element from in front of queue and returns that element. */
public int pop() {
in2out();
return out.pop();
}
/** Get the front element. */
public int peek() {
in2out();
return out.peek();
}
/** Returns whether the queue is empty. */
public boolean empty() {
return in.isEmpty()&&out.isEmpty();
}
public void in2out(){
if(out.isEmpty()){
while(!in.isEmpty()){
out.push(in.pop());
}
}
}
}
/**
* Your MyQueue object will be instantiated and called as such:
* MyQueue obj = new MyQueue();
* obj.push(x);
* int param_2 = obj.pop();
* int param_3 = obj.peek();
* boolean param_4 = obj.empty();
*/
225.用队列实现栈
题目大意
请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通队列的全部四种操作(push、top、pop 和 empty)。
实现 MyStack 类:
- void push(int x) 将元素 x 压入栈顶。
- int pop() 移除并返回栈顶元素。
- int top() 返回栈顶元素。
- boolean empty() 如果栈是空的,返回 true ;否则,返回 false
解题思路
将一个元素x
插入队列时,为了维护原来后进先出的顺序,需要让x
插入队列首部。而队列的默认插入方式是队列尾部,因此在将x
插入队列尾部之后,需要让除了x
之外的所有元素出队列,再入队列。
队列的相关操作
- 定义一个队列:
Queue<Integer> queue=new LinkedList<>();
- 添加元素:
queue.add(x);
- 获取队列头的元素:
queue.poll();
将首个元素从队列中弹出,如果队列是空的,就返回null。
- 查看队首元素:
queue.peek();
查看首个元素,不会移除首个元素,如果队列是空就返回null。
- 查看首个元素:
queue.element();
查看首个元素,不会移除首个元素,如果队列是空的就抛出异常NoSuchElementException
- 队首元素出队列
queue.remove();
- 队列的大小:
queue.size();
- 判断队列是否为空
queue.isEmpty();
代码实现
class MyStack {
//定义一个队列
private Queue<Integer> queue;
/** Initialize your data structure here. */
public MyStack() {
queue=new LinkedList<>();
}
/** Push element x onto stack. */
public void push(int x) {
queue.add(x);
int cnt=queue.size();
while(cnt-->1){
queue.add(queue.poll());
}
}
/** Removes the element on top of the stack and returns that element. */
public int pop() {
return queue.remove();
}
/** Get the top element. */
public int top() {
return queue.peek();
}
/** Returns whether the stack is empty. */
public boolean empty() {
return queue.isEmpty();
}
}
155.最小栈
题目大意
设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。
- push(x) —— 将元素 x 推入栈中。
- pop() —— 删除栈顶的元素。
- top() —— 获取栈顶元素。
- getMin() ——检索栈中的最小元素。
解题思路
定义一个最小栈,栈顶元素一直是栈内元素的最小值。
代码实现
class MinStack {
Stack<Integer> dataStack;
Stack<Integer> minStack;
int min;
/** initialize your data structure here. */
public MinStack() {
dataStack=new Stack<>();
minStack=new Stack<>();
min=Integer.MAX_VALUE;
}
public void push(int val) {
dataStack.add(val);
min=Math.min(val,min);
minStack.add(min);
}
public void pop() {
dataStack.pop();
minStack.pop();
min=minStack.isEmpty()?Integer.MAX_VALUE:minStack.peek();
}
public int top() {
return dataStack.peek();
}
public int getMin() {
return minStack.peek();
}
}
20.有效的括号
题目大意
给定一个只包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字符串 s ,判断字符串是否有效。
有效字符串需满足:
- 左括号必须用相同类型的右括号闭合。
- 左括号必须以正确的顺序闭合。
解题思路
取出字符串中的每一个元素,如果是左括号就压入栈中,如果是右括号与栈顶的元素匹配,那么就将栈顶元素出栈,最后查看栈是否为空。
代码实现
class Solution {
public boolean isValid(String s) {
//利用栈来实现
Stack<Character> stack=new Stack<>();
int i=0;
for(char c:s.toCharArray()){
if(c=='('||c=='['||c=='{'){
stack.push(c);
}else{
if(stack.isEmpty()){
return false;
}
char cStack=stack.pop();
boolean b1=c==')'&&cStack!='(';
boolean b2=c==']'&&cStack!='[';
boolean b3=c=='}'&&cStack!='{';
if(b1||b2||b3){
return false;
}
}
}
return stack.isEmpty();
}
}
739.每日温度
题目大意
请根据每日 气温 列表,重新生成一个列表。对应位置的输出为:要想观测到更高的气温,至少需要等待的天数。如果气温在这之后都不会升高,请在该位置用 0 来代替。
例如,给定一个列表temperatures = [73, 74, 75, 71, 69, 72, 76, 73]
,你的输出应该是[1, 1, 4, 2, 1, 1, 0, 0]
。
解题思路
利用栈来实现,栈存放的是数组对应的索引值,如果当前元素小于栈顶的元素的时候就将该索引值压入栈中,如果大于栈顶的元素,那么该元素就是第一个大于栈顶元素对应数值的数,计算他们之间的数值差即可。
代码实现
class Solution {
public int[] dailyTemperatures(int[] T) {
//栈保存的是索引
Stack<Integer> stack=new Stack<>();
int n=T.length;
int[] res=new int[n];
for(int i=0;i<n;i++){
while(!stack.isEmpty()&&T[i]>T[stack.peek()]){
int preindex=stack.pop();
res[preindex]=i-preindex;
}
stack.add(i);
}
return res;
}
}
503.下一个更大元素 II
题目大意
给定一个循环数组(最后一个元素的下一个元素是数组的第一个元素),输出每个元素的下一个更大元素。数字 x 的下一个更大的元素是按数组遍历顺序,这个数字之后的第一个比它更大的数,这意味着你应该循环地搜索它的下一个更大的数。如果不存在,则输出 -1。
解题思路
与上题的解题思路类似,只不过这是一个循环数组并且返回的是第一个比它大的数不是索引了。
利用栈来实现,因为是循环数组,所以对数组遍历两边来实现循环数组的效果,对数组遍历的时候,边遍历边往栈中加入元素,如果当前元素比栈顶元素大,那么就将该数作为栈顶元素对应的数值,如果当前数组比栈顶元素对应的数组还小也直接入栈。
代码实现
class Solution {
public int[] nextGreaterElements(int[] nums) {
int n=nums.length;
int[] next=new int[n];
Arrays.fill(next,-1);
Stack<Integer> stack=new Stack<>();
for(int i=0;i<2*n;i++){
int num=nums[i%n];
while(!stack.isEmpty()&&nums[stack.peek()]<num){
next[stack.pop()]=num;
}
if(i<n){
stack.push(i);
}
}
return next;
}
}