常见的栈与队列算法题
1.使用队列实现栈
2.使用栈实现队列
3.包含最小值函数的栈
4.合法的出栈序列
5.简单计算器
1.队列实现栈
class MyStack { public: /** Initialize your data structure here. */ MyStack() { } /** Push element x onto stack. */ void push(int x) { int len=data.size(); data.push(x); while(len>0){ data.push(data.front()); data.pop(); len--; } } /** Removes the element on top of the stack and returns that element. */ int pop() { int res=data.front(); data.pop(); return res; } /** Get the top element. */ int top() { return data.front(); } /** Returns whether the stack is empty. */ bool empty() { return data.empty(); } private: std::queue<int> data; }; /** * 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(); */
主要是push函数的编写。x进队后,让之前的元素 一 一 出队再入队。
2.栈实现队列
class MyQueue { public: /** Initialize your data structure here. */ MyQueue() { } /** Push element x to the back of queue. */ void push(int x) { while(s.size()){ s_temp.push(s.top()); s.pop(); } s.push(x); while(s_temp.size()){ s.push(s_temp.top()); s_temp.pop(); } } /** Removes the element from in front of queue and returns that element. */ int pop() { int res=s.top(); s.pop(); return res; } /** Get the front element. */ int peek() { return s.top(); } /** Returns whether the queue is empty. */ bool empty() { return s.empty(); } private: std::stack<int> s,s_temp; }; /** * 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(); */
3.最小值栈
设计一个支持 push,pop,top 操作,并能在常数时间内检索到最小元素的栈。
- push(x) -- 将元素 x 推入栈中。
- pop() -- 删除栈顶的元素。
- top() -- 获取栈顶元素。
- getMin() -- 检索栈中的最小元素。
class MinStack { public: /** initialize your data structure here. */ MinStack() { } void push(int x) { s.push(x); if(sMin.empty() || x <= sMin.top()){ sMin.push(x); } } void pop() { if(s.top()==sMin.top()){ s.pop(); sMin.pop(); }else{ s.pop(); } } int top() { return s.top(); } int getMin() { return sMin.top(); } private: std::stack<int> s,sMin; }; /** * Your MinStack object will be instantiated and called as such: * MinStack obj = new MinStack(); * obj.push(x); * obj.pop(); * int param_3 = obj.top(); * int param_4 = obj.getMin(); */
用另一个栈sMin记录最小值。空间复杂度O(n).
4.合法的出栈序列
class Solution { public: bool validateStackSequences(vector<int>& pushed, vector<int>& popped) { stack<int> s; int len=pushed.size(); int i=0,j=0; while(i<len){ s.push(pushed[i++]); while(!s.empty()){ if(s.top()==popped[j]){ s.pop(); j++; }else{ break; } } } return s.empty(); } };
借助一个栈s,模拟进出栈顺序。遍历pushed数组,先将元素进栈。然后再开一个出栈循环,若栈不空,将栈顶与popped数组元素比较,相同则出栈,继续下一个循环;不同则跳出出栈循环,继续外面的进栈操作。最后返回是否栈空。以上应该是最为清晰的思路了,之前我也写过两个,一个暴力法判断,时间复杂度较高,逻辑也很复杂;另一个也是模拟进出栈,但是思路太乱,代码逻辑冗余混乱,简单来说就是模拟的不够真实,反而导致自己思路不畅。
5.简单计算器
实现一个基本的计算器来计算一个简单的字符串表达式的值。
字符串表达式可以包含左括号 (
,右括号 )
,加号 +
,减号 -
,非负整数和空格 。
class Solution { private: stack<int> num; stack<char> sign; void compute(stack<int> &num, stack<char> &sign) { int num2 = num.top(); num.pop(); int num1 = num.top(); num.pop(); if (sign.top() == '+') num.push(num1 + num2); else if (sign.top() == '-') num.push(num1 - num2); sign.pop(); } public: int calculate(string s) { int len = s.size(); if (len == 0) return 0; int temp = 0; for (int i = 0; i < len; i++) { if (s[i] == ' ') continue; else if (s[i] == '(') { sign.push(s[i]); continue; } else if (s[i] >= '0' && s[i] <= '9') { temp = s[i] - '0'; while (i + 1 != len && s[i + 1] >= '0' && s[i + 1] <= '9') { temp = temp * 10 + s[i+1] - '0'; i++; } num.push(temp); temp = 0; } else if (s[i] == '+' || s[i] == '-') { sign.push(s[i]); continue; } else if (s[i] == ')') { if (sign.top() != '(') { compute(num, sign); } sign.pop(); } if (!sign.empty()&& sign.top() != '(') { compute(num,sign); } } return num.top(); } };
括号也入栈,否则即使结果正确也不符合括号规定的顺序,主要是这里只有加减法,也不出错。