用栈模拟队列和用队列模拟栈
leetcode.232
- 链接leetcode.cn/problems/im…
- 解题方法:栈:先入后出,队列:先入先出
取栈顶元素,取队头元素:top(),front()
栈、队列判空:empty()
栈、队列添加元素:push()
栈、队列删除元素:pop()
- leetcode解题代码
class MyQueue {
public:
stack<int> a, b
MyQueue() {
}
void push(int x) {
a.push(x)
}
int pop() {
while (a.size() > 1) b.push(a.top()), a.pop()
int cur = a.top()
a.pop()
while (b.size()) a.push(b.top()), b.pop()
return cur
}
int peek() {
while (a.size() > 1) b.push(a.top()), a.pop()
int cur = a.top()
while (b.size()) a.push(b.top()), b.pop()
return cur
}
bool empty() {
return a.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()
*/
leetcode.225
- 链接leetcode.cn/problems/im…
- 解题方法:栈:先入后出,队列:先入先出
取栈顶元素,取队头元素:top(),front()
栈、队列判空:empty()
栈、队列添加元素:push()
栈、队列删除元素:pop()
- leetcode解题代码
class MyStack {
public:
queue<int> a, b
MyStack() {
}
void push(int x) {
a.push(x)
}
int pop() {
while (a.size() > 1) b.push(a.front()), a.pop()
int cur = a.front()
a.pop()
while (b.size()) a.push(b.front()), b.pop()
return cur
}
int top() {
while (a.size() > 1) b.push(a.front()), a.pop()
int cur = a.front()
a.pop()
while (b.size()) a.push(b.front()), b.pop()
a.push(cur)
return cur
}
bool empty() {
return a.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()
*/
用栈先入后出的性质解题
leetcode.20
class Solution {
public:
bool isValid(string s) {
stack<char> stk;
for (auto c: s){
if (c == '(' || c == '[' || c == '{') stk.push(c);
else if (c == ')'){
if (stk.empty() || stk.top() != '(')
return false;
stk.pop();
}
else if (c == ']'){
if (stk.empty() || stk.top() != '[')
return false;
stk.pop();
}
else if (c == '}'){
if (stk.empty() || stk.top() != '{')
return false;
stk.pop();
}
}
return stk.empty();
}
};
- 解题方法2:先将所有的左括号入栈,注意入栈顺序要跟匹配顺序相同
匹配右括号,可以查询ASKII码发现无论是大中小括号,其左右括号的ASKII码相差小于等于2
- leetcode解题代码
class Solution {
public:
bool isValid(string s) {
stack<char> stk;
for (auto c: s){
if (c == '(' || c == '[' || c == '{') stk.push(c);
else {
if (stk.empty() || abs(c - stk.top()) > 2) return false;
stk.pop();
}
}
return stk.empty();
}
};
leetcode.1047
- 链接leetcode.cn/problems/re…
- 解题方法:遍历所有字符,如果栈不空且栈顶元素与遍历的当前元素相同,删除栈顶元素,否则将当前元素加入栈中
遍历栈加入答案数组,由于栈是先入后出所以需要反转一下答案数组
- leetcode解题代码
class Solution {
public:
string removeDuplicates(string s) {
stack<char> stk;
string res;
for (auto c: s){
if (stk.size() && stk.top() == c) stk.pop();
else stk.push(c);
}
while (stk.size()){
res += stk.top();
stk.pop();
}
reverse(res.begin(), res.end());
return res;
}
};
leetcode.150
- 链接leetcode.cn/problems/ev…
- 解题方法:遍历所有字符,如果字符为运算符则将当前栈顶的两个元素弹出做相应计算(注意:弹出是先弹出后面的元素,减法和除法需要注意元素计算顺序)
如果字符为数字,则入栈(注意转换格式)
- leetcode解题代码
class Solution {
public:
int evalRPN(vector<string>& tokens) {
stack<int> stk
for (auto c: tokens){
if (c == "+" || c == "-" || c == "*" || c == "/"){
long b = stk.top()
long a = stk.top()
if (c == "+") stk.push(a + b)
else if (c == "-") stk.push(a - b)
else if (c == "*") stk.push(a * b)
else if (c == "/") stk.push(a / b)
}
else stk.push(stoi(c))
}
return stk.top()
}
}
单调栈
- 常见模型:找出每个数左边/右边离它最近的比它大/小的数
- 单调栈模板
for (int i = 0; i < n; i ++ )
{
while (stk.size() && check(stk[tt], i)){
}
stk.push();
}
leetcode.496
- 链接leetcode.cn/problems/ne…
- 解题方法:在nums2中用单调栈模板找出所有当前数下一个更大的元素用数组q存储
用哈希表存储nums2元素对应下标
在nums1中利用哈希表和数组q找对应的下一个更大元素
- leetcode解题代码
class Solution {
public:
vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {
stack<int> stk;
vector<int> q(nums2.size());
// 若当前元素大于栈顶元素,记录并删除栈顶元素,将当前元素入栈
for (int i = 0; i < nums2.size(); i ++){
int x = nums2[i];
while (stk.size() && x > nums2[stk.top()]){
int t = stk.top();
stk.pop();
q[t] = nums2[i];
}
stk.push(i);
}
// 大于栈顶元素的记录过了,小于的没入栈剩下的都是等于的,将其赋值为-1
while (stk.size()){
q[stk.top()] = -1;
stk.pop();
}
unordered_map<int, int> hash;
for (int i = 0; i < nums2.size(); i ++) hash[nums2[i]] = i;
vector<int> res;
for (auto c: nums1){
res.push_back(q[hash[c]]);
}
return res;
}
};
leetcode.503
class Solution {
public:
vector<int> nextGreaterElements(vector<int>& nums) {
int n = nums.size()
nums.insert(nums.end(), nums.begin(), nums.end())
stack<int> stk
vector<int> res(2 * n)
for (int i = 0
int x = nums[i]
while (stk.size() && x > nums[stk.top()]){
int t = stk.top()
stk.pop()
res[t] = nums[i]
}
stk.push(i)
}
while (stk.size()){
res[stk.top()] = -1
stk.pop()
}
res.resize(n)
return res
}
}
leetcode.739
class Solution {
public:
vector<int> dailyTemperatures(vector<int>& temperatures) {
int n = temperatures.size()
stack<int> stk
vector<int> res(n)
for (int i = 0
int x = temperatures[i]
while (stk.size() && x > temperatures[stk.top()]){
int t = stk.top()
stk.pop()
res[t] = i - t
}
stk.push(i)
}
return res
}
}
单调队列
- 常见模型:找出滑动窗口中的最大最小值
- 如果求滑动窗口的最大值那么即为一个递减序列(队头为最大值)
- 如果求滑动窗口的最小值那么即为一个递增序列(队头为最小值)
- 单调队列模板
for (int i = 0; i < n; i ++ )
{
while (q.size() && check()) q.pop_front();
while (q.size() && check()) q.pop_back();
q.push_back(i);
if (i >= k - 1) res.push_back();
}
leetcode.239
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
deque<int> q;
vector<int> res;
for (int i = 0; i < nums.size(); i ++){
while (q.size() && i - q.front() + 1 > k) q.pop_front();
while (q.size() && nums[i] >= nums[q.back()]) q.pop_back();
q.push_back(i);
if (i >= k - 1) res.push_back(nums[q.front()]);
}
return res;
}
};
优先队列
- 优先队列是一种会按照默认或自定义的优先级进行自动排序的队列,其特点是优先级高的元素排在队首,低的排在队尾,可以理解为维护一个堆
- 头文件
#include <queue>中提供了两种可直接引用的优先规则(排序规则):greater、less;其中,less是默认优先规则,大根堆,可以理解为从堆顶元素向下逐渐减小;greater表示小根堆,堆顶元素向下逐渐变大
leetcode.215
class Solution {
public:
int findKthLargest(vector<int>& nums, int k) {
priority_queue<int, vector<int>, greater<int>> heap;
for (auto c: nums){
heap.push(c);
if (heap.size() > k){
heap.pop();
}
}
return heap.top();
}
};
leetcode.347
class Solution {
public:
vector<int> topKFrequent(vector<int>& nums, int k) {
unordered_map<int, int> hash;
for (auto c: nums) hash[c] ++;
struct mycompare{
bool operator () (const pair<int, int> &a, const pair<int, int> &b){
return a.second > b.second;
}
};
priority_queue<pair<int, int>, vector<pair<int, int>>, mycompare> heap;
for (auto x: hash){
heap.push(x);
if (heap.size() > k){
heap.pop();
}
}
vector<int> res;
while (heap.size()){
res.push_back(heap.top().first);
heap.pop();
}
return res;
}
};