232. 用栈实现队列 - 力扣(LeetCode)
请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(
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(双端队列)来模拟一个栈,只要是标准的栈操作即可。
push的对象永远是stack_inpop的对象永远是stack_out- 只有
stack_out为空时,才会获取stack_in的元素
stack_out非空时,不需要stack_in补充也能完成popstack_out非空时,获取stack_in的元素只能加在栈顶,而他们是晚入队的元素,在栈顶会早出队,不符合队列规则
- 获取
stack_in的元素时必须完全获取
- 需要
stack_in的元素说明下一个pop的对象是stack_in栈底的元素,如果全部入栈stack_out,后续pop全乱套
class MyQueue {
public:
stack<int> stackin;
stack<int> stackout;
MyQueue() {
}
void push(int x) {
stackin.push(x);//push的对象永远是stack_in
}
int pop() {
if(stackout.empty()){ //如果stackout空,从stackin里获取所有元素
while(stackin.empty()==0){
stackout.push(stackin.top());
stackin.pop();
}
}
int res = stackout.top();
stackout.pop();//pop的对象永远是stack_out
return res;
}
int peek() {//复用。先删后补
int res = this->pop();
stackout.push(res);
return res;
}
bool empty() {
return stackin.empty()&&stackout.empty();
}
};
关于初见这题,我自己的想法
还是要用到第二个栈,像是两个杯子,stack1先倒给stack2,2倒掉栈顶(也就是1的栈底),再倒回给1。空间复杂度是一样的,但时间复杂度更高,高了不少。由于是自己想到的,还是写出来记录一下。
注意 如果用这种方法,
peek()无法先调用pop()再调用push()补回去,因为始终只有一个栈,stack2只是相当于一个交换两数时用到的temp。完成pop()后,stack2是空栈,stack1删除了栈底元素且没法直接补回栈底元素。
但处理逻辑跟pop()一模一样,只是少了删除stack2栈顶的这一步(第二十行),只需要记录即可。
class MyQueue {
public:
stack<int> stack1;
stack<int> stack2;//创建一个栈,来回倒
MyQueue() {
}
void push(int x) {
stack1.push(x);
}
int pop() {
while(stack1.empty()==0){
stack2.push(stack1.top());
stack1.pop();
}
int ans = stack2.top();//记录栈顶元素
stack2.pop();
while(!stack2.empty()){
stack1.push(stack2.top());
stack2.pop();
}
return ans;
}
int peek() {
stack<int> stack2;//创建一个栈,来回倒
while(!stack1.empty()){
stack2.push(stack1.top());
stack1.pop();
}
int ans = stack2.top();//记录栈顶元素
while(!stack2.empty()){
stack1.push(stack2.top());
stack2.pop();
}
return ans;
}
bool empty() {
return stack1.empty();
}
};
225. 用队列实现栈 - 力扣(LeetCode)
请你仅使用两个队列实现一个后入先出(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(双端队列)来模拟一个队列 , 只要是标准的队列操作即可。
一次AC^_^
栈顶就是队尾,如果执行pop,stack会删除栈顶,对应到队列就是队尾元素。因此应想办法让队尾元素插队到队首,并保持其他元素相对位置不变。(第一变第二、倒二变倒一)
class MyStack {
public:
queue<int> q;
MyStack() {
}
void push(int x) {
q.push(x);
}
int pop() {
int depth = q.size();//栈顶等同于队尾
while(--depth){ //除队尾,其余元素出队再入队,等同于绕圈
q.push(q.front());
q.pop();
}
//此时,绕圈前的队尾在队首,其他元素都已套圈第二次入队排在后面
int result = q.front();
q.pop();
return result;
}
int top() {
int stack_top_element = this->pop();
q.push(stack_top_element);
return stack_top_element;
}
bool empty() {
return q.empty();
}
};
20. 有效的括号 - 力扣(LeetCode)
给定一个只包括
'(',')','{','}','[',']'的字符串s,判断字符串是否有效。有效字符串需满足:
- 左括号必须用相同类型的右括号闭合。
- 左括号必须以正确的顺序闭合。
- 每个右括号都有一个对应的相同类型的左括号。
之前做过,接受右括号会执行stack.top()查看当前元素和栈顶元素是否匹配。当第一个元素就是右括号时,栈为空,stack.top()会报错,应该先检查栈是否为空。除此之外一次写对^_^
class Solution {
public:
bool isValid(string s) {
stack<char> stack;
for(char i:s){
if(i=='['||i=='('||i=='{'){//左括号入栈
stack.push(i);
}
else{
if(stack.empty()) return false;//【就是这里,记得先判断是否为空】
else if(couple(stack.top())==i) stack.pop();
else return false;//【栈非空,遇到右括号且不与栈顶元素匹配,最后不可能全部匹配】
}
}
return stack.empty();
}
char couple(char in){
if(in == '[') return ']';
else if(in == '(') return ')';
else return '}';
}
};
1047. 删除字符串中的所有相邻重复项 - 力扣(LeetCode)
给出由小写字母组成的字符串
s,重复项删除操作会选择两个相邻且相同的字母,并删除它们。在
s上反复执行重复项删除操作,直到无法继续删除。在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。
class Solution {
public:
string removeDuplicates(string s) {
stack<char> stack;
for(char i : s){
if(stack.empty()){//如果空栈,直接入栈
stack.push(i);
}
else{
if(i==stack.top()){
stack.pop(); //如果连连看成功,连同栈顶元素一同删除
}
else stack.push(i);//连连看不成功,入栈
}
}
//将栈中元素转为字符串
int size = stack.size();
string ans(size,' ');
for(int i = size-1;i>=0;i--){
ans[i] = stack.top();
stack.pop();
}
return ans;
}
};