代码随想录算法训练营第十一天|栈与队列专题一
今日内容:
-
leetcode 232.用栈实现队列
-
leetcode 225. 用队列实现栈
-
leetcode 20. 有效的括号
-
leetcode 1047. 删除字符串中的所有相邻重复项
leetcode 232.用栈实现队列
题目链接:leetcode 232.用栈实现队列
题目详情:
思路
题目要求使用两个栈来实现队列,首先我们需要知道栈和队列的特性是什么?栈是先进后出的一种数据结构,而队列是先进先出的一种数据结构。那么如何使用两个先进后出的结构实现一个先进先出的结构呢?
我的思路是我们可以使用一个栈用来存放输入的数据,而当我们需要peek或者pop元素时,我们只需要将输入栈中的数据全部弹出存放到输出栈中。为什么需要这样做呢?因为输入栈存放的顺序时逆序的,当弹出存放到输出栈中时就会再次变成顺序。当下次在需要pop或者peek时可以直接在输出栈中pop或peek。若输出栈为空那么再从输入栈从弹出存放到输出栈即可。队列为空就是输入栈和输出栈全为空的时候。
动图演示:
代码
class MyQueue {
//输入栈
Stack<Integer> input_stack=new Stack<>();
//输出栈
Stack<Integer> output_stack=new Stack<>();
public MyQueue() {
}
public void push(int x) {
input_stack.push(x);
}
public int pop() {
if(!output_stack.isEmpty()){
return output_stack.pop();
}else{
if(input_stack.isEmpty()){
return -1;
}else{
while(!input_stack.isEmpty()){
output_stack.push(input_stack.pop());
}
return output_stack.pop();
}
}
}
public int peek() {
if(!output_stack.isEmpty()){
return output_stack.peek();
}else{
if(input_stack.isEmpty()){
return -1;
}else{
while(!input_stack.isEmpty()){
output_stack.push(input_stack.pop());
}
return output_stack.peek();
}
}
}
public boolean empty() {
if(input_stack.isEmpty() && output_stack.isEmpty()){
return true;
}
return false;
}
}
/**
* 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();
*/
leetcode 225. 用队列实现栈
题目链接:leetcode 225. 用队列实现栈
题目详情:
思路
基础:
使用两个队列如何实现栈呢?因为我们需要做到先进后出,所以我们使用一个队列来push元素,另一个队列是起到备份作用。当需要pop元素时,那么就是将最新push的元素pop,而队列只能pop最早push的元素,所以我们可以将队列一中的元素全部备份到队列二中(除了需要弹出的元素)。
动图演示:
进阶:
因为题目没有要求不能使用双端队列,如果我们使用双端队列的话,就可以直接利用双端队列的性质直接实现。那么如果我们不使用双端队列,那么我们应该怎么实现呢?
一个队列在模拟栈弹出元素的时候只要将队列头部的元素(除了最后一个元素外) 重新添加到队列尾部,此时在去弹出元素就是栈的顺序了。也就是说是不需要使用第二个队列备份,直接将元素重新push到本队列的队尾即可。
方法一(使用两个队列)
class MyStack {
Queue<Integer> queue1;
Queue<Integer> queue2;
/** Initialize your data structure here. */
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();
}
}
leetcode 20. 有效的括号
题目链接:leetcode 20. 有效的括号
题目详情:
思路
括号匹配问题是使用栈解决的经典问题,本题我们可以碰到左括号的话可以将对应的右括号push到栈中,如果碰到右括号则与栈顶元素比较,如果相等,则说明该右括号可以与栈顶元素匹配,如果不等或者栈为空的话,那么说明左右括号不匹配,直接返回false,如果遍历到最后栈为空的话则说明括号全部匹配,否则就是还有左括号没有对应的右括号与之匹配。
动图演示:
代码
class Solution {
public boolean isValid(String s) {
Stack<Character> stack =new Stack<>();
for(int i=0;i<s.length();i++){
char ch=s.charAt(i);
if(ch=='('){
stack.push(')');
}else if(ch=='['){
stack.push(']');
}else if(ch=='{'){
stack.push('}');
}else if(stack.isEmpty() || stack.peek()!=ch){
return false;
}else{
stack.pop();
}
}
return stack.isEmpty();
}
}
leetcode 1047. 删除字符串中的所有相邻重复项
题目链接:leetcode 1047. 删除字符串中的所有相邻重复项
题目详情:
思路
本题要删除相邻相同元素,相对于上一题来说其实也是匹配问题,上一题是匹配左右括号,本题是匹配相邻元素,最后都是做消除的操作。本题也是用栈来解决的经典题目。
那么栈里应该放的是什么元素呢?
我们在删除相邻重复项的时候,其实就是要知道当前遍历的这个元素,我们在前一位是不是遍历过一样数值的元素,那么如何记录前面遍历过的元素呢?
所以就是用栈来存放,那么栈的目的,就是存放遍历过的元素,当遍历当前的这个元素的时候,去栈里看一下我们是不是遍历过相同数值的相邻元素。然后再去做对应的消除操作。
动图演示:
代码
class Solution {
public String removeDuplicates(String s) {
if(s.length()==1){
return s;
}
Stack<Character> stack =new Stack<>();
for(int i=0;i<s.length();i++){
char ch =s.charAt(i);
if(stack.isEmpty()){
stack.push(ch);
continue;
}
char temp =stack.peek();
if(ch==temp){
stack.pop();
continue;
}else{
stack.push(ch);
}
}
String res="";
while(!stack.isEmpty()){
char temp = stack.pop();
res = temp+res;
}
return res;
}
}