一、用栈实现队列
1.题目:请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push
、pop
、peek
、empty
):
2.思路:
使用两个栈 stIn 和 stOut,
(1)当需要 pop() 移除队首时,把 stIn 所有元素移动到 stOut 里,然后从 stOut 移除栈尾元素
(2)当需要 push() 添加队尾元素时,把 stOut 全部移动到 stIn 里,然后向 stIn 添加栈尾元素
(3)当需要 peek() 时,类似 pop()
(4)当需要 empty() 判断时,直接调用栈的 isempty() 对 stIn 和 stOut 判断
3.注意:
4.代码:
class MyQueue {
public:
stack<int> stIn;
stack<int> stOut;
/** Initialize your data structure here. */
MyQueue() {
}
/** Push element x to the back of queue. */
void push(int x) {
stIn.push(x);
}
/** Removes the element from in front of queue and returns that element. */
int pop() {
// 只有当stOut为空的时候,再从stIn里导入数据(导入stIn全部数据)
if (stOut.empty()) {
// 从stIn导入数据直到stIn为空
while(!stIn.empty()) {
stOut.push(stIn.top());
stIn.pop();
}
}
int result = stOut.top();
stOut.pop();
return result;
}
/** Get the front element. */
int peek() {
int res = this->pop(); // 直接使用已有的pop函数
stOut.push(res); // 因为pop函数弹出了元素res,所以再添加回去
return res;
}
/** Returns whether the queue is empty. */
bool empty() {
return stIn.empty() && stOut.empty();
}
};
二、用队列实现栈
1.题目:请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(push
、top
、pop
和 empty
)。
2.思路:
创建两个队列 que1 和 que2
(1)当需要 pop() 移除栈尾时,把 que1 所有非末尾元素移动到 que2 里,然后将que1清空,再把 que2 元素移回 que1
(2)当需要 push() 添加队尾元素时,直接向 que1 添加
(3)当需要 top() 时,类似 pop()
(4)当需要 empty() 判断时,直接调用队列的 isempty() 对 que1 判断
3.注意:
与队列实现栈不同的是,此处 que2 仅用于备份元素,操作结束后元素返回 que1
4.代码:
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() {
int size = que1.size();
size--;
while (size--) { // 将que1 导入que2,但要留下最后一个元素
que2.push(que1.front());
que1.pop();
}
int result = que1.front(); // 留下的最后一个元素就是要返回的值
que1.pop();
que1 = que2; // 再将que2赋值给que1
while (!que2.empty()) { // 清空que2
que2.pop();
}
return result;
}
/** Get the top element.
** Can not use back() direactly.
*/
int top(){
int size = que1.size();
size--;
while (size--){
// 将que1 导入que2,但要留下最后一个元素
que2.push(que1.front());
que1.pop();
}
int result = que1.front(); // 留下的最后一个元素就是要回返的值
que2.push(que1.front()); // 获取值后将最后一个元素也加入que2中,保持原本的结构不变
que1.pop();
que1 = que2; // 再将que2赋值给que1
while (!que2.empty()){
// 清空que2
que2.pop();
}
return result;
}
/** Returns whether the stack is empty. */
bool empty() {
return que1.empty();
}
};
三、有效的括号
1.题目:给定一个只包括 '('
,')'
,'{'
,'}'
,'['
,']'
的字符串 s
,判断字符串是否有效。有效字符串需满足:
左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
每个右括号都有一个对应的相同类型的左括号。
2.思路:
3.注意:
当字符串出现 ')' ']' '}',调用栈的 top() 时需要判断栈是否为空。
4.代码:
法一:
class Solution {
public:
bool isValid(string s) {
stack<char> myStack;
for(int i=0; i<s.size(); i++)
{
if( s[i]=='(' || s[i]== '[' || s[i]== '{')
{
myStack.push(s[i]);
}else if(s[i]==')'){
if( myStack.empty() || myStack.top() != '(' )
return false;
myStack.pop();
}else if(s[i]==']'){
if( myStack.empty() || myStack.top() != '[' )
return false;
myStack.pop();
}else if(s[i]=='}'){
if( myStack.empty() || myStack.top() != '{' )
return false;
myStack.pop();
}
}
return myStack.empty();
}
};
法二:
class Solution {
public:
bool isValid(string s) {
if (s.size() % 2 != 0) return false; // 如果s的长度为奇数,一定不符合要求
stack<char> st;
for (int i = 0; i < s.size(); i++) {
if (s[i] == '(') st.push(')');
else if (s[i] == '{') st.push('}');
else if (s[i] == '[') st.push(']');
// 第三种情况:遍历字符串匹配的过程中,栈已经为空了,没有匹配的字符了,说明右括号没有找到对应的左括号 return false
// 第二种情况:遍历字符串匹配的过程中,发现栈里没有我们要匹配的字符。所以return false
else if (st.empty() || st.top() != s[i]) return false;
else st.pop(); // st.top() 与 s[i]相等,栈弹出元素
}
// 第一种情况:此时我们已经遍历完了字符串,但是栈不为空,说明有相应的左括号没有右括号来匹配,所以return false,否则就return true
return st.empty();
}
};
四、 删除字符串中的所有相邻重复项
1.题目:给出由小写字母组成的字符串 S
,重复项删除操作会选择两个相邻且相同的字母,并删除它们。在 S 上反复执行重复项删除操作,直到无法继续删除。在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。
2.思路:
3.注意:
(1)题目中说的删除操作时两个相邻,所以无需考虑3个及以上相邻的情况
(2)在用栈记录字符串元素后再转为字符串时记得反序。
4.代码:
class Solution {
public:
string stackToStr(stack<char> charStack)
{
string output;
stack<char> tempStack; // 创建临时栈以迭代
while( !charStack.empty() )
{
tempStack.push(charStack.top());
charStack.pop();
}
while (!tempStack.empty())
{
output += tempStack.top();
tempStack.pop();
}
return output;
}
string removeDuplicates(string s) {
stack<char> myStack;
for(int i=0; i<s.size(); i++)
{
if( !myStack.empty() && myStack.top() == s[i] )
{
myStack.pop();
}else{
myStack.push(s[i]);
}
}
return stackToStr(myStack);
}
};