一、用栈实现队列
栈是单开口,队列双开口,想用栈实现队列,必须要用两个栈来才能实现。第一个栈用于实现队列的储存元素,第二个栈用于实现队列的释放元素。
通过这题我学到了在c++中,栈的操作可以有:
1. .push(x)压栈
2. .pop()出栈
3. .top()获取栈顶元素
4. .empty()判断是否为空,若为空则值为1
class MyQueue {
public:
stack<int>stIn;
stack<int>stOut;
MyQueue() {
}
void push(int x) {
stIn.push(x);
}
int pop() {
if(stOut.empty()){
while(!stIn.empty()){
stOut.push(stIn.top());
stIn.pop();
}
}
int result=stOut.top();
stOut.pop();
return result;
}
int peek() {
if(stOut.empty()){
while(!stIn.empty()){
stOut.push(stIn.top());
stIn.pop();
}
}
int result=stOut.top();
return result;
}
bool empty() {
if(stOut.empty()&&stIn.empty())return true;
else 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();
*/
二、队列实现栈
这题用我的思路和题解一样,都是先把队列首元素加到队尾,然后再删除队首元素。不过在控制循环的时候,我一开始用了让temp等于队尾元素(模拟栈顶),直到让队首元素等于temp时,停止队首加队尾这个操作。这样的问题是,如果队列中有重复的元素像用例中[1,2,2,3,4,2],temp=2,而到第二个元素就停止删除了,所以会出现错误。改用题解用size存放队列长度的方法,通过控制size的大小来控制循环的起止。
C++中队列涉及的操作:
1. .pop()
2. .push()
3. .front()返回队首元素(不删除)
4. .back()返回队尾元素(不删除)
class MyStack {
public:
queue<int>q;
MyStack() {
}
void push(int x) {
q.push(x);
}
int pop() {
int _size=q.size();
_size--;
while(_size--){
q.push(q.front());
q.pop();
}
int result=q.front();
q.pop();
return result;
}
int top() {
return q.back();
}
bool empty() {
if(q.empty())return true;
else return false;
}
};
/**
* 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();
*/
三、有效的括号
本题第一次尝试是开辟了三个栈,分别存放()、{}、【】,然后判断他们的大小是不是偶数来判断是否不是正确的括号,但是这个样只能判断括号数是否正确,如果存在({)}这样的次序问题就会出错。
第一次错误代码:
class Solution {
public:
stack<char>st1;
stack<char>st2;
stack<char>st3;
bool isValid(string s) {
for(int i=0;i<s.size();i++){
if(s[i]=='('||s[i]==')')
st1.push(s[i]);
else if(s[i]=='['||s[i]==']')
st2.push(s[i]);
else if(s[i]=='{'||s[i]=='}')
st3.push(s[i]);
else continue;
}
if(st1.size()%2!=0||st2.size()%2!=0||st3.size()%2!=0)return false;
else return true;
}
};
第二次根据题解,重新理解题意。发现字符串全部是由括号组成的。因此在遍历过程中既可用压栈操作录入左括号,又可以出栈退出右括号。本题录入的方法是,如果检测到左括号,那么压入右括号,等到左括号全部检索完毕后,根据检索到的右括号和已压入的右括号进行一一比对。栈在比对过程时不能为空,比对完毕后必须为空,这是两个判断条件,另外如果比对不成功也就是s[i]!=st.top()时也是一个错误的条件
class Solution {
public:
stack<char>st;
bool isValid(string s) {
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(']');
}
else if(st.empty()){
return false;
}
else if(s[i]!=st.top()){
return false;
}
else{
st.pop();
}
}
if(st.empty()!=1)return false;
return true;
}
};
四、删除字符串中的所有相邻重复项
本题操作思路跟题解一样,这里学习到了如何返回,首先要string一个变量(之前还在C语言定义字符数组依次赋值的思路没有转变),然后用+=直接拼接字符串,最后用reverse函数反转一下即可。
class Solution {
public:
string removeDuplicates(string s) {
stack<char>st;
for(int i=0;i<s.size();i++){
if(st.empty()||s[i]!=st.top()){
st.push(s[i]);
}//如果栈顶没有出现则录入
else{
st.pop();
}//如果出现与栈顶相同的说明相邻重复
}
string result="";
while(!st.empty()){
result+=st.top();
st.pop();
}
reverse(result.begin(),result.end());
return result;
}
};