232.用栈实现队列
题目描述
题目链接:力扣232.用栈实现队列
请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(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(双端队列)来模拟一个栈,只要是标准的栈操作即可。
思路
已知栈是先进后出,队列是先进先出,要使用两个栈实现队列的功能,只需要在取数时让栈1的数据依次挪到栈2,再取栈2的顶部数据即可。
将一个栈当作输入栈,用于压入 push 传入的数据;另一个栈当作输出栈,用于 pop 和 peek 操作。
每次 pop 或 peek 时,若输出栈为空则将输入栈的全部数据依次弹出并压入输出栈,这样输出栈从栈顶往栈底的顺序就是队列从队首往队尾的顺序。
代码实现
class MyQueue {
private:
stack<int> inStack, outStack;
void in2out() {
while (!inStack.empty()) {
outStack.push(inStack.top());
inStack.pop();
}
}
public:
MyQueue() {}
void push(int x) {
inStack.push(x);
}
int pop() {
if (outStack.empty()) {
in2out();
}
int x = outStack.top();
outStack.pop();
return x;
}
int peek() {
if (outStack.empty()) {
in2out();
}
return outStack.top();
}
bool empty() {
return inStack.empty() && outStack.empty();
}
};
225.用队列实现栈
题目描述
题目链接:力扣225.用队列实现栈
请你仅使用两个队列实现一个后入先出(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(双端队列)来模拟一个队列 , 只要是标准的队列操作即可。
思路
由于栈的特性是先入先出,在使用队列实现栈时,应满足队列前端的元素最后入栈,可以使用两个队列实现栈的操作,其中 q u e u e 1 queue_1 queue1 用于存储栈内的元素, q u e u e 2 queue_2 queue2 作为入栈的辅助队列。
入栈时,首先将元素入队到 q u e u e 2 queue_2 queue2,然后将 q u e u e 1 queue_1 queue1 的元素全部出队并入队到 q u e u e 2 queue_2 queue2,此时 q u e u e 2 queue_2 queue2 的前端元素即为新入栈的元素,再将 q u e u e 1 queue_1 queue1 和 q u e u e 2 queue_2 queue2 互换,则 q u e u e 1 queue_1 queue1 的元素为栈内的元素即为栈内的元素, q u e u e 1 queue_1 queue1 的前端和后端分别对应栈顶和栈底。
判断栈空时,只需要判断 q u e u e 1 queue_1 queue1 是否为空即可。
代码实现
class MyStack {
public:
queue<int> queue1;
queue<int> queue2;
/** Initialize your data structure here. */
MyStack() {
}
/** Push element x onto stack. */
void push(int x) {
queue2.push(x);
while (!queue1.empty()) {
queue2.push(queue1.front());
queue1.pop();
}
swap(queue1, queue2);
}
/** Removes the element on top of the stack and returns that element. */
int pop() {
int r = queue1.front();
queue1.pop();
return r;
}
/** Get the top element. */
int top() {
int r = queue1.front();
return r;
}
/** Returns whether the stack is empty. */
bool empty() {
return queue1.empty();
}
};
20.有效的括号
题目描述
题目链接:力扣20.有效的括号
给定一个只包括 '('
,')'
,'{'
,'}'
,'['
,']'
的字符串 s ,判断字符串是否有效。
有效字符串需满足:
- 左括号必须用相同类型的右括号闭合。
- 左括号必须以正确的顺序闭合。
- 每个右括号都有一个对应的相同类型的左括号。
思路
顺序遍历字符串,碰到左括号就入栈,碰到右括号就判断和栈顶元素是否匹配,匹配就出栈,不匹配就说明字符串无效。
代码实现
class Solution {
public:
bool isValid(string s) {
char stack[10001];
int top =0;
for (int i = 0; s[i]; ++i) {
if (s[i] == '(' || s[i] == '[' || s[i] == '{') stack[top++] = s[i];
else {
if ((--top) < 0) return false;//先减减,让top指向栈顶元素
if (s[i] == ')' && stack[top] != '(') return false;
if (s[i] == ']' && stack[top] != '[') return false;
if (s[i] == '}' && stack[top] != '{') return false;
}
}
return (!top);//防止“【”这种类似情况
}
};
1047. 删除字符串中的所有相邻重复项
题目描述
给出由小写字母组成的字符串 S,重复项删除操作会选择两个相邻且相同的字母,并删除它们。
在 S 上反复执行重复项删除操作,直到无法继续删除。
在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。
思路
和括号匹配问题类似,只要顺序遍历字符串,碰到和栈顶元素不一样就入栈,一样就出栈,最后从栈底顺序输出即可。
代码实现
class Solution {
public:
string removeDuplicates(string s) {
char stack[100005];
int top = 0;
for(int i = 0; i < s.size(); i++){
if(top == 0 || s[i] != stack[top - 1]){
stack[top++] = s[i];
}
else if(s[i] == stack[top - 1]){
top --;
}
}
string res;
for(int i = 0; i < top; i++){
res += stack[i];
}
return res;
}
};
LCR 036. 逆波兰表达式求值
题目描述
题目链接:力扣LCR 036.逆波兰表达式求值
根据 逆波兰表示法,求该后缀表达式的计算结果。
有效的算符包括 +
、-
、*
、/
。每个运算对象可以是整数,也可以是另一个逆波兰表达式。
说明:
- 整数除法只保留整数部分。
- 给定逆波兰表达式总是有效的。换句话说,表达式总会得出有效数值且不存在除数为 0 的情况。
思路
根据逆波兰表达式的计算方法,很容易想到栈的数据结构。
顺序遍历表达式,如果是数字就入栈,如果是算符就取出栈顶两个元素,按算符计算,再将结果入栈,如此遍历结束,栈中应只剩一个元素,表达式的值。
注意:取出栈顶两个元素时,注意两个数的操作顺序,对除法会有影响。
代码实现
class Solution {
public:
int string2int(string s){
int i = 0;
if(s[0] == '-') i = 1;
int num = 0;
while(i < s.size()){
num = num * 10 + s[i] - '0';
i++;
}
if(s[0] == '-') return -num;
return num;
}
bool isOperator(string s){
return s == "+" || s == "-" || s == "*" || s == "/";
}
int evalRPN(vector<string>& tokens) {
int stack[10004], top = 0;
for(int i = 0; i < tokens.size(); i++){
if(top == 0 || !isOperator(tokens[i])){
stack[top++] = string2int(tokens[i]);
}
else if(isOperator(tokens[i])){
int t = 0;
int b = stack[--top], a = stack[--top];
if(tokens[i] == "+") t = a + b;
if(tokens[i] == "-") t = a - b;
if(tokens[i] == "*") t = a * b;
if(tokens[i] == "/") t = a / b;
stack[top++] = t;
}
}
return stack[--top];
}
};