232 用栈实现队列
题目理解
用两个栈实现队列的功能,支持队列的所有操作。
栈只能使用基本操作。
思路
队列是先进先出,栈是后进先出。怎样用栈实现先进先出的功能呢,用两个栈,一个入,一个出。
当执行队列的push操作时,入栈push;执行队列的pop操作时,需要把栈中最先进入的元素pop出,因此需要将入栈依次pop(),然后push到出栈中,直到入栈为空,此时栈中最先进入的元素就是出栈的top()元素。
查询队首元素,与队列的pop()操作类似,因此,可以在pop()的基础上,读出队首元素,再把pop出来的队首元素push进去即可。
判断队列是否为空,只需要出栈和入栈都为空,则队列为空。
代码
class MyQueue {
public:
stack<int> In;
stack<int> Out;
/** Initialize your data structure here. */
MyQueue() {
}
/** Push element x to the back of queue. */
void push(int x) {
In.push(x);
}
/** Removes the element from in front of queue and returns that element. */
int pop() {
if(Out.empty())
{
while(!In.empty()) {
Out.push(In.top());
In.pop();
}
}
int res = Out.top();
Out.pop();
return res;
}
/** Get the front element. */
int peek() {
int res = this->pop();
Out.push(res);
return res;
}
/** Returns whether the queue is empty. */
bool empty() {
if(Out.empty() && In.empty())
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();
* bool param_4 = obj->empty();
*/
225 用队列实现栈
题目理解
用两个队列实现栈的基本功能,队列只能使用基本操作(push、pop、size、empty)
思路
不同于用栈实现队列,队列是先进先出,栈是后进先出,怎样让栈中后进的元素先出来呢,我们需要把栈中先进去的元素存起来,这样才能让后进去的元素先出来,因此使用两个队列,一个队列存另一个队列最后进来的元素之前的元素。
push操作,只需要往队列push即可。
pop操作,则需另一个队列把当前队列的前size-1个元素存起来,然后pop当前队列的元素,最后再把另一个队列存储的元素移回到原队列。
top操作,与pop操作类似,只需把pop出的栈顶元素在push进去即可。
empty操作需要判断原队列是否为空即可。
代码
class MyStack {
public:
queue<int> que1;
queue<int> que2;
/** Initialize your data structure here. */
MyStack() {
}
/** Push element x onto stack. */
void push(int x) {
que1.push(x);
}
/** Removes the element on top of the stack and returns that element. */
int pop() {
while(que1.size() != 1) {
que2.push(que1.front());
que1.pop();
}
int res = que1.front();
que1.pop();
while(que2.size()) {
que1.push(que2.front());
que2.pop();
}
return res;
}
/** Get the top element. */
int top() {
int res = this->pop();
que1.push(res);
return res;
}
/** Returns whether the stack is empty. */
bool empty() {
return que1.empty();
}
};
/**
* Your MyStack object will be instantiated and called as such:
* MyStack* obj = new MyStack();
* obj->push(x);
* int param_2 = obj->pop();
* int param_3 = obj->top();
* bool param_4 = obj->empty();
*/
20 有效的括号
题目理解
字符串只由() {} []组成,判断字符串中的括号是否匹配。
思路
对称匹配类的题目,适合使用栈来解决。可以遍历字符串,当遇到’(’ ‘{’ ‘[‘时,向栈中压入对应的’)’ ‘}’ ‘]’,然后在遇到’)’ ‘}’ ‘]’,判断栈顶元素是否和当前元素相等,相等则pop,不相等则显然不匹配。
代码
class Solution {
public:
bool isValid(string s) {
stack<char> st;
if(s.size() == 1) return false;
for(auto c : s) {
if(c == '(')
st.push(')');
else if(c == '{')
st.push('}');
else if(c == '[')
st.push(']');
else if(st.empty() || st.top() != c) //栈为空或者栈顶元素不等于当前字符说明不匹配
return false;
else st.pop();
}
if(st.empty()) //遍历完后如果栈不为空说明不匹配
return true;
return false;
}
};
1047 删除字符串中的所有相邻重复项
题目理解
如果字符串相邻元素相等,则删除相等元素,如果删除以后导致目前相邻的元素相等,则目前的重复元素也要删除。
思路
和栈的操作非常相似,如果当前元素和栈顶元素相等,则弹出栈顶元素,再比较,相等则再弹出。最后栈中剩下的元素即为不重复的元素,又因为栈是后进先出,因此最后要反转字符串得到结果。
代码
class Solution {
public:
string removeDuplicates(string S) {
stack<char> st;
string res;
for(auto c : S) {
if (st.empty() || c != st.top())
st.push(c);
else {
st.pop();
}
}
while(!st.empty()) {
res += st.top();
st.pop();
}
reverse(res.begin(),res.end());
return res;
}
};
150 逆波兰表达式求值
题目理解
根据逆波兰表示法,求表达式的值。
如"2",“1”,"+",“3”,"*",结果为((2 + 1) * 3) = 9。
逆波兰表示法就是将运算符前两个数字进行相应操作。
思路
使用栈即可解决,将数字压入栈,当遇到运算符时,取出栈顶两个元素进行运算,将运算结果压入栈,以此往复,直到遍历完数组。运算结果即为最后的栈顶元素。
代码
class Solution {
public:
int evalRPN(vector<string>& tokens) {
stack<int> st;
for(auto c : tokens) {
if(st.empty() || (c != "+" && c != "-" && c != "*" && c != "/"))
st.push(stoi(c));
else {
int num1 = st.top();
st.pop();
int num2 = st.top();
st.pop();
if(c == "+")
st.push(num1 + num2);
else if(c == "-")
st.push(num2 - num1);
else if(c == "*")
st.push(num1 * num2);
else st.push(num2 / num1);
}
}
return st.top();
}
};