栈
栈(Stack) 是一种常见的线性数据结构,具有后进先出(LIFO, Last In First Out)的特点。栈就像生活中的书堆或碟子堆,只能在一端进行操作:新元素从顶端加入,移除时也只能从顶端取出。
用数组模拟栈
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
| #include <iostream> using namespace std;
const int N = 100010; int stk[N], tt = -1;
void push(int x) { stk[++tt] = x; }
void pop() { tt--; }
void empty() { if (tt == -1) cout << "YES" << endl; else cout << "NO" << endl; }
void query() { cout << stk[tt] << endl; }
int main() { int M; cin >> M; int x; while (M--) { string op; cin >> op; if (op == "push") { cin >> x; push(x); } else if (op == "pop") { pop(); } else if (op == "empty") { empty(); } else { query(); } } return 0; }
|
单调栈
暴力
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| void solve() { int n; cin >> n; vector<int> arr(n); for (int i = 0; i < n; i++) cin >> arr[i]; vector<int> left; vector<int> right; for (int i = 0; i < n; i++) { int pos_l = -1, pos_r = -1; for (int j = i; j >= 0; j--) { if (arr[j] < arr[i]) { pos_l = j; break; } } for (int j = i; j < n; j++) { if (arr[j] < arr[i]) { pos_r = j; break; } } if (pos_l != -1) left.push_back(arr[pos_l]); else left.push_back(pos_l); if (pos_r != -1) right.push_back(arr[pos_r]); else right.push_back(pos_r); } for (int i = 0; i < n; i++) cout << left[i] << " "; cout << endl; for (int i = 0; i < n; i++) cout << right[i] << " "; cout << endl; }
|
左程云版
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| void solve() {
int n; cin >> n; vector<int> arr(n); for (int i = 0; i < n; i++) cin >> arr[i]; vector<int> left(n, -1); vector<int> right(n, -1); stack<int> stk; for (int i = 0; i < n; i++) { while (!stk.empty() && arr[i] <= arr[stk.top()]) { stk.pop(); } if (!stk.empty()) left[i] = arr[stk.top()]; stk.push(i); } while (!stk.empty()) stk.pop(); for (int i = n - 1; i >= 0; i--) { while (!stk.empty() && arr[i] <= arr[stk.top()]) { stk.pop(); } if (!stk.empty()) right[i] = arr[stk.top()]; stk.push(i); } for (int i = 0; i < n; i++) cout << left[i] << " "; cout << endl; for (int i = 0; i < n; i++) cout << right[i] << " "; cout << endl; }
|
acwing版
https://www.acwing.com/problem/content/832/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| #include <iostream> using namespace std;
const int N = 100010; int stk[N], tt;
int main() { ios::sync_with_stdio(0);cin.tie(0),cout.tie(0); int N; cin >> N; while (N--) { int x; cin >> x; while (tt > 0 && stk[tt] >= x) tt--; if (tt == 0) cout << -1 << " "; else cout << stk[tt] << " "; stk[++tt] = x; }
return 0; }
|
习题
Colorful Bracket Sequence
https://atcoder.jp/contests/abc394/tasks/abc394_d
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| #include <bits/stdc++.h> #define int long long using namespace std;
void solve() { string str; cin >> str; stack<char> stk; for (int i = 0; i < str.size(); i++) { if (str[i] == '(' || str[i] == '[' || str[i] == '<') { stk.push(str[i]); } else { if (!stk.empty()) { if (stk.top() == '(' && str[i] == ')' || stk.top() == '[' && str[i] == ']' || stk.top() == '<' && str[i] == '>') { stk.pop(); } else { cout << "No" << endl; return; } } else { cout << "No" << endl; return; } } } if (stk.empty()) { cout << "Yes" << endl; } else { cout << "No" << endl; } }
signed main(){ ios::sync_with_stdio(0);cin.tie(0);cout.tie(0); int t = 1; while (t--) solve(); return 0; }
|
每日温度
https://leetcode.cn/problems/daily-temperatures/description/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| class Solution { public: vector<int> dailyTemperatures(vector<int>& temperatures) { int n = temperatures.size(); vector<int> ans(n), right(n, -1); stack<int> stk; for (int i = n - 1; i >= 0; i--) { while (!stk.empty() && temperatures[i] >= temperatures[stk.top()]) { stk.pop(); } if (!stk.empty()) right[i] = stk.top(); stk.push(i); } for (int i = 0; i < n; i++) { if (right[i] != -1) ans[i] = right[i] - i; } return ans; } };
|
子数组的最小值之和
https://leetcode.cn/problems/sum-of-subarray-minimums/description/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| class Solution { const int mod = 1e9 + 7; public: int sumSubarrayMins(vector<int>& arr) { int n = arr.size(); long long sum = 0; vector<int> left(n, -1), right(n, n); stack<int> stk; for (int i = 0; i < n; i++) { while (!stk.empty() && arr[i] <= arr[stk.top()]) { stk.pop(); } if (!stk.empty()) left[i] = stk.top(); stk.push(i); } while (!stk.empty()) stk.pop(); for (int i = n - 1; i >= 0; i--) { while (!stk.empty() && arr[i] < arr[stk.top()]) { stk.pop(); } if (!stk.empty()) right[i] = stk.top(); stk.push(i); } for (int i = 0; i < n; i++) { sum = (sum + (long)(i - left[i]) * (right[i] - i) * arr[i] % mod ) % mod; } return sum; } };
|
柱状图中的最大矩形
https://leetcode.cn/problems/largest-rectangle-in-histogram/description/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| class Solution { public: int largestRectangleArea(vector<int>& arr) { int n = arr.size(); vector<int> left(n, -1), right(n, n); int ans = INT_MIN; stack<int> stk; for (int i = 0; i < n; i++) { while (!stk.empty() && arr[i] <= arr[stk.top()]) { stk.pop(); } if (!stk.empty()) left[i] = stk.top(); stk.push(i); } while (!stk.empty()) stk.pop(); for (int i = n - 1; i >= 0; i--) { while (!stk.empty() && arr[i] <= arr[stk.top()]) { stk.pop(); } if (!stk.empty()) right[i] = stk.top(); stk.push(i); } for (int i = 0; i < n; i++) { ans = max(ans, (right[i] - left[i] - 1) * arr[i]); } return ans; } };
|
最大矩形
https://leetcode.cn/problems/maximal-rectangle/description/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
| int largestRectangleArea(vector<int>& arr) { int n = arr.size(); vector<int> left(n, -1), right(n, n); int ans = INT_MIN; stack<int> stk; for (int i = 0; i < n; i++) { while (!stk.empty() && arr[i] <= arr[stk.top()]) { stk.pop(); } if (!stk.empty()) left[i] = stk.top(); stk.push(i); } while (!stk.empty()) stk.pop(); for (int i = n - 1; i >= 0; i--) { while (!stk.empty() && arr[i] <= arr[stk.top()]) { stk.pop(); } if (!stk.empty()) right[i] = stk.top(); stk.push(i); } for (int i = 0; i < n; i++) { ans = max(ans, (right[i] - left[i] - 1) * arr[i]); } return ans; }
class Solution { public: int maximalRectangle(vector<vector<char>>& matrix) { int n = matrix.size(); int m = matrix[0].size(); int ans = INT_MIN; vector<int> arr(m); for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { if (i == 0) arr[j] = matrix[i][j] - '0'; else { if (matrix[i - 1][j] == '1' && matrix[i][j] == '1') arr[j]++; if (matrix[i - 1][j] == '1' && matrix[i][j] == '0') arr[j] = 0; if (matrix[i - 1][j] == '0' && matrix[i][j] == '1') arr[j] = 1; if (matrix[i - 1][j] == '0' && matrix[i][j] == '0') arr[j] = 0; } } ans = max(ans, largestRectangleArea(arr)); } return ans; } };
|