5. 栈与队列
-
用栈实现队列: https://leetcode-cn.com/problems/implement-queue-using-stacks/
class MyQueue { private: stack<int> inStack, outStack; void in2out() { while (!inStack.empty()) { outStack.push(inStack.top()); inStack.pop(); } } public: MyQueue() {} void push(int x) { inStack.push(x); } int pop() { if (outStack.empty()) { in2out(); } int x = outStack.top(); outStack.pop(); return x; } int peek() { if (outStack.empty()) { in2out(); } return outStack.top(); } bool empty() { return inStack.empty() && outStack.empty(); } }; /** * 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(); */ 复杂度分析 时间复杂度:push 和 empty 为O(1),pop 和 peek 为均摊O(1)。对于每个元素,至多入栈和出栈各两次,故均摊复杂度为 O(1)。 空间复杂度:O(n)。其中 n 是操作总数。对于有n 次push 操作的情况,队列中会有 n 个元素,故空间复杂度为O(n)。
-
用队列实现栈: https://leetcode-cn.com/problems/implement-stack-using-queues/
class MyStack { public: queue<int> queue1; queue<int> queue2; //数据初始化 MyStack() { } //将元素x压入栈中 void push(int x) { queue2.push(x); while (!queue1.empty()) { queue2.push(queue1.front()); // front() 返回当前vector容器中起始元素的引用。 queue1.pop(); } swap(queue1, queue2); } //移除栈顶的元素,并返回该元素 int pop() { int r = queue1.front(); queue1.pop(); return r; } //获取栈顶元素 int top() { int r = queue1.front(); return r; } //返回栈是空 bool empty() { return queue1.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(); */ 复杂度分析 时间复杂度:入栈操作 O(n),其余操作都是O(1),其中 n 是栈内的元素个数。入栈操作需要将queue1中的 nn 个元素出队,并入队 n+1 个元素到 queue2 ,共有 2n+1 次操作,每次出队和入队操作的时间复杂度都是O(1),因此入栈操作的时间复杂度是O(n)。 出栈操作对应将queue1的前端元素出队,时间复杂度是 O(1)。获得栈顶元素操作对应获得 queue 1的前端元素,时间复杂度是O(1)。 判断栈是否为空操作只需要判断queue1是否为空,时间复杂度是O(1)。 空间复杂度:O(n),其中 nn 是栈内的元素个数。需要使用两个队列存储栈内的元素。
-
最小栈: https://leetcode-cn.com/problems/min-stack/
class MinStack { stack<int> x_stack; stack<int> min_stack; public: MinStack() { min_stack.push(INT_MAX); } void push(int val) { x_stack.push(val); min_stack.push(min(min_stack.top(), val)); } void pop() { x_stack.pop(); min_stack.pop(); } int top() { return x_stack.top(); } int getMin() { return min_stack.top(); } }; 复杂度分析 时间复杂度:对于题目中的所有操作,时间复杂度均为 O(1)。因为栈的插入、删除与读取操作都是 O(1),我们定义的每个操作最多调用栈 操作两次。 空间复杂度:O(n),其中n 为总操作数。最坏情况下,我们会连续插入 n 个元素,此时两个栈占用的空间为 O(n)。
-
有效的括号: https://leetcode-cn.com/problems/valid-parentheses/
class Solution { public: bool isValid(string s) { int n = s.size(); if (n % 2 == 1) { return false; } unordered_map<char, char> pairs = { {')', '('}, {']', '['}, {'}', '{'} }; stack<char> stk; for (char ch: s) { if (pairs.count(ch)) { if (stk.empty() || stk.top() != pairs[ch]) { return false; } stk.pop(); } else { stk.push(ch); } } return stk.empty(); } }; 复杂度分析 时间复杂度:O(n),其中 n 是字符串 s 的长度。 空间复杂度:O(n+∣Σ∣),其中Σ 表示字符集,本题中字符串只包含 6 种括号,∣Σ∣=6。栈中的字符数量为O(n),而哈希表使用的空间为 O(∣Σ∣),相加即可得到总空间复杂度。
-
每日温度: https://leetcode-cn.com/problems/daily-temperatures/
class Solution { public: vector<int> dailyTemperatures(vector<int>& temperatures) { int n = temperatures.size(); vector<int> ans(n); //创建一个长度大小为n的数组 stack<int> s; //创建一个s的栈 for (int i = 0; i < n; i++) { while (!s.empty() && temperatures[i] > temperatures[s.top()]) { int previousIndex = s.top(); ans[previousIndex] = i - previousIndex; s.pop(); } s.push(i); } return ans; } };
-
下一个更大元素 II: https://leetcode-cn.com/problems/next-greater-element-ii/
class Solution { public: vector<int> nextGreaterElements(vector<int>& nums) { int n = nums.size(); vector<int> ret(n, -1); stack<int> stk; for (int i = 0; i < n * 2 - 1; i++) { while (!stk.empty() && nums[stk.top()] < nums[i % n]) { ret[stk.top()] = nums[i % n]; stk.pop(); } stk.push(i % n); } return ret; } };