algorithm generalized-monotonic-stack(A, cmp, process) stack S ← ∅ for i ← 0 to n-1 do: while S ≠ ∅ and condition(A[i], A[S.top()]) do: // 栈的单调性被破坏,while是为了让栈里满足条件的元素都可以出栈 j ← S.pop() // 栈顶出栈 recordAnswer(j, i) // 计算并记录栈顶对应的答案 end while S.push(i) // 栈为空或者栈的单调性没有被破坏,则新元素一定不是某个元素的答案,入栈 end for end algorithm
// 柱状图最大矩形 while (!st.empty() && heights[i] < heights[st.top()]) { int h = heights[st.top()]; st.pop(); int w = st.empty() ? i : i - st.top() - 1; maxArea = max(maxArea, h * w); }
// 每日温度(计算距离) while (!st.empty() && temps[i] > temps[st.top()]) { int j = st.top(); st.pop(); result[j] = i - j; // 距离 }
3. 典型例题
例1:下一个更大元素
1 2 3 4 5 6 7 8 9 10 11 12 13 14
vector<int> nextGreaterElement(vector<int>& nums){ int n = nums.size(); vector<int> result(n, -1); stack<int> st; for (int i = 0; i < n; i++) { while (!st.empty() && nums[i] > nums[st.top()]) { result[st.top()] = nums[i]; st.pop(); } st.push(i); } return result; }
intlargestRectangleArea(vector<int>& heights){ stack<int> st; heights.push_back(0); // 哨兵,这是为了保证最后一个元素也能出栈 int maxArea = 0; for (int i = 0; i < heights.size(); i++) { while (!st.empty() && heights[i] < heights[st.top()]) { int h = heights[st.top()]; st.pop(); int w = st.empty() ? i : i - st.top() - 1; maxArea = max(maxArea, h * w); } st.push(i); } return maxArea; }
例3:接雨水
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
inttrap(vector<int>& height){ stack<int> st; int water = 0; for (int i = 0; i < height.size(); i++) { while (!st.empty() && height[i] > height[st.top()]) { int bottom = st.top(); st.pop(); if (st.empty()) break; int distance = i - st.top() - 1; int h = min(height[i], height[st.top()]) - height[bottom]; water += distance * h; } st.push(i); } return water; }