单调栈

[Algo] 单调栈

基本模板:

vector<vector<int>> lessThanIndex(vector<int> &arr)
{
    int len = arr.size();
    vector<vector<int>> ans(len, vector<int>(2, 0));
    stack<int> s;
    for (int i = 0; i < len; i++)
    {
        while (!s.empty() && arr[i] <= arr[s.top()])
        {
            int index = s.top();
            s.pop();
            ans[index][0] = s.empty() ? -1 : s.top();
            ans[index][1] = i;
        }
        s.push(i);
    }
    while (!s.empty())
    {
        int index = s.top();
        s.pop();
        ans[index][0] = s.empty() ? -1 : s.top();
        ans[index][1] = -1;
    }
    // 存在相等元素时,需要对ans[i][1]进行修正
    for (int i = len - 1; i >= 0; i--)
    {
        if (ans[i][1] != -1 && arr[i] == arr[ans[i][1]]) ans[i][1] = ans[ans[i][1]][1];
    }
    return ans;
}

1. 柱状图中的最大矩形

// 1. 柱状图中的最大矩形
// https://leetcode.cn/problems/largest-rectangle-in-histogram/description/
int largestRectangleArea(vector<int>& heights) {
    vector<vector<int>> v = lessThanIndex(heights);
    int max_size = 0;
    for (int i = 0; i < heights.size(); i++)
    {
        int l = v[i][0] == -1 ? 0 : v[i][0] + 1;
        int r = v[i][1] == -1 ? heights.size() - 1 : v[i][1] - 1;
        max_size = max(max_size, (r - l + 1) * heights[i]);
    }
    return max_size;
}

2. 最大矩形

// 2. 最大矩形
// https://leetcode.cn/problems/maximal-rectangle/description/
int maximalRectangle(vector<vector<char>>& matrix) {
    int n = matrix.size(), m = matrix[0].size();
    vector<int> heights(m, 0);
    int max_size = 0;
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < m; j++) heights[j] = matrix[i][j] == '1' ? heights[j] + 1 : 0;
        max_size = max(max_size, largestRectangleArea(heights));
    }
    return max_size;
}

3. 最大宽度坡

// 3. 最大宽度坡
// https://leetcode.cn/problems/maximum-width-ramp/
int maxWidthRamp(vector<int>& nums) {
    stack<int> s;
    int len = nums.size(), ans = 0;
    for (int i = 0; i < len; i++) if (s.empty() || nums[i] < nums[s.top()]) s.push(i);
    for (int i = len - 1; i >= 0; i--)
    {
        while (!s.empty() && nums[i] >= nums[s.top()])
        {
            ans = max(ans, i - s.top());
            s.pop();
        }
    }
    return ans;
}

4. 去除重复字母,保证返回结果的字典序最小

// 4. 去除重复字母,保证返回结果的字典序最小
// https://leetcode.cn/problems/remove-duplicate-letters/
string removeDuplicateLetters(string s) {
    unordered_map<char, int> letter;
    for (char ch : s) letter[ch]++;
    stack<char> stk;
    unordered_set<char> set;
    for (int i = 0; i < s.length(); i++)
    {
        letter[s[i]]--;
        if (set.find(s[i]) != set.end()) continue;
        while (!stk.empty() && s[i] <= stk.top() && letter[stk.top()] > 0)
        {
            set.erase(stk.top());
            stk.pop();
        }
        stk.push(s[i]);
        set.insert(s[i]);
    }
    string ans;
    while (!stk.empty())
    {
        ans += stk.top();
        stk.pop();
    }
    reverse(ans.begin(), ans.end());
    return ans;
}

5. 统计全1子矩形

// 5. 统计全1子矩形
// https://leetcode.cn/problems/count-submatrices-with-all-ones/description/
int numMat(vector<int>& mat) {
    int len = mat.size();
    stack<int> s;
    int ans = 0;
    for (int i = 0; i < len; i++)
    {
        while (!s.empty() && mat[s.top()] >= mat[i])
        {
            int index = s.top();
            s.pop();
            if (mat[index] > mat[i])
            {
                int l = s.empty() ? -1 : s.top();
                int r = i;
                int width = (r - l) * (r - l - 1) / 2;
                int lval = l == -1 ? 0 : mat[l];
                int rval = mat[r];
                int height = mat[index] - max(lval, rval);
                ans += width * height;
            }
        }
        s.push(i);
    }
    while (!s.empty())
    {
        int index = s.top();
        s.pop();
        int l = s.empty() ? -1 : s.top();
        int r = len;
        int width = (r - l) * (r - l - 1) / 2;
        int lval = l == -1 ? 0 : mat[l];
        int rval = r == len ? 0 : mat[r];
        int height = mat[index] - max(lval, rval);
        ans += width * height;
    }
    return ans;
}
int numSubmat(vector<vector<int>>& mat)
{
    int n = mat.size(), m = mat[0].size();
    vector<int> heights(m, 0);
    int ans = 0;
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < m; j++) heights[j] = mat[i][j] == 0 ? 0 : heights[j] + 1;
        ans += numMat(heights);
    }
    return ans;
}
posted @ 2024-12-28 14:35  yaoguyuan  阅读(15)  评论(0)    收藏  举报