单调栈 (Monotone-Stack) 及经典问题

单调栈

单调栈:不从头部出的单调队列

总结
单调队列:擅长维护区间【最大/最小】值,最小值对应单调递增队列
单调栈:擅长维护最近【大于/小于】关系
从左侧先入栈,就是维护左侧最近关系
从右侧先入栈,就是维护右侧最近关系

int main(){
	int n;
	cin>>n;
	vector<int> arr(n);
	vector<int> pre(n), nxt(n);
	stack<int> s;
	for(int i = 0, a;i < n; ++i) cin >> arr[i];
	for(int i = 0; i < n; i++){
		while(s.size() && arr[i] < arr[s.top()]){
			nxt[s.top()] = i;
			s.pop();
		}
		if(s.size() == 0) pre[i] = -1;
		else pre[i] = s.top();
		s.push(i);
	}
	while(s.size()) nxt[s.top()] = n, s.pop();
	return 0;
}

单调栈基础题目

155. 最小栈

class MinStack {
public:
    stack<int> s, min_s;
    MinStack() {}
    
    void push(int val) {
        s.push(val);
        if(min_s.size() == 0 || val <= min_s.top()){
            min_s.push(val);
        }
        return;
    }
    
    void pop() {
        if(s.top() == min_s.top()) min_s.pop();
        s.pop();
        return;
    }
    
    int top() {
        return s.top();
    }
    
    int getMin() {
        return min_s.top();
    }
};

503. 下一个更大元素 II

class Solution {
public:
    vector<int> nextGreaterElements(vector<int>& nums) {
        stack<int> s;
        vector<int> ret(nums.size());
        for(int i = 0; i < nums.size(); i++) ret[i] = -1;
        for(int i = 0; i < nums.size(); i++){
            while(s.size() && nums[i] > nums[s.top()]){
                ret[s.top()] = nums[i];
                s.pop();
            }
            s.push(i);
        }
        for(int i = 0; i < nums.size(); i++){
            while(s.size() && nums[i] > nums[s.top()]){
                ret[s.top()] = nums[i];
                s.pop();
            }
            s.push(i);
        }
        return ret;
    }
};

901.股票价格跨度

class StockSpanner {
public:
    typedef pair<int, int> PII;
    int t;
    stack<PII> s;
    StockSpanner() {
        t = 0;
        s.push(PII(INT_MAX, t++));
    }
    
    int next(int price) {
        while(s.size() && price >= s.top().first) s.pop();
        int ret = t - s.top().second;
        s.push(PII(price, t++));
        return ret;
    }
};

739. 每日温度

class Solution {
public:
    vector<int> dailyTemperatures(vector<int>& temperatures) {
        vector<int> ret(temperatures.size());
        stack<int> s;
        for(int i = 0; i < temperatures.size(); ++i){
            while(s.size() && temperatures[i] > temperatures[s.top()]){
                ret[s.top()] = i - s.top();
                s.pop();
            }
            s.push(i);
        }
        return ret;
    }
};

84. 柱状图中最大的矩形

class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        stack<int> s;
        vector<int> l(heights.size()), r(heights.size());
        int n = heights.size();
        for(int i = 0; i < n; i++) l[i] = -1, r[i] = n;
        for(int i = 0; i < n; i++) {
            while(s.size() && heights[i] <= heights[s.top()]){
                r[s.top()] = i;
                s.pop();
            }
            if(s.size()) l[i] = s.top();
            s.push(i);
        }
        int ans = 0;
        for(int i = 0; i < n; i++){
            ans = max(ans, heights[i] * (r[i] - l[i] - 1));
        }
        return ans;
    }
};

1856. 子数组最小乘积的最大值

class Solution {
public:
    int maxSumMinProduct(vector<int>& nums) {
        stack<int> s;
        vector<int> l(nums.size()), r(nums.size());
        int n = nums.size();
        for(int i = 0; i < n; i++) l[i] = -1, r[i] = n;
        for(int i = 0; i < n; i++) {
            while(s.size() && nums[i] <= nums[s.top()]){
                r[s.top()] = i;
                s.pop();
            }
            if(s.size()) l[i] = s.top();
            s.push(i);
        }
        vector<long long> sum(n + 1);
        sum[0] = 0;
        for(int i = 0; i < n; i++) sum[i + 1] = sum[i] + nums[i];
        long long ans = 0;
        for(int i = 0; i < n; i++){
            ans = max(ans, nums[i] * (sum[r[i]] - sum[l[i] + 1]));
        }
        return ans % (long long)(1e9 + 7); 
    }
};

907. 子数组的最小值之和

class Solution {
public:
    int sumSubarrayMins(vector<int>& arr) {
        stack<int> s;
        int mod_num = 1e9 + 7;
        long long ans = 0;
        vector<long long> sum(arr.size() + 1);
        sum[0] = 0;
        for(int i = 0; i < arr.size(); i++){
            while(s.size() && arr[i] <= arr[s.top()]) s.pop();
            int ind = s.size() ? s.top() : -1;
            s.push(i);
            sum[s.size()] = (sum[s.size() - 1] + arr[i] * (i - ind)) % mod_num;
            ans += sum[s.size()];
            ans %= mod_num;
        }
        return ans;
    }
};

496. 下一个更大元素 I

class Solution {
public:
    vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {
        unordered_map<int, int> h;
        stack<int> s;
        for(auto x: nums2){
            while(s.size() && x > s.top()){
                h[s.top()] = x;
                s.pop();
            }
            s.push(x);
        }
        vector<int> ret(nums1.size());
        for(int i = 0; i < nums1.size(); i++){
            if(h.find(nums1[i]) == h.end()) ret[i] = -1;
            else ret[i] = h[nums1[i]]; 
        }
        return ret;
    }
};

456. 132 模式

  • 假设当前元素是中间的最大值,那么需要向前寻找小于他的最小值和向后找大于他的最大值,进行比较看是否符合条件
class Solution {
public:
    bool find132pattern(vector<int>& nums) {
        vector<int> l(nums.size());
        l[0] = INT_MAX;
        for(int i = 1; i < nums.size(); i++) l[i] = min(l[i - 1], nums[i - 1]);
        stack<int> s;
        for(int i = nums.size() - 1; i >= 0; --i){
            int val = nums[i] + 1;
            while(s.size() && nums[i] > s.top()) val = s.top(), s.pop();
            s.push(nums[i]);
            if(l[i] < nums[i] && val < nums[i] && val > l[i]) return true;
        }
        return false;
    }
};

42. 接雨水

class Solution {
public:
    int trap(vector<int>& height) {
        int ans = 0;
        stack<int> s;
        for(int i = 0; i < height.size(); i++){
            while(s.size() && height[i] > height[s.top()]){
                int now = s.top();
                s.pop();
                if(s.size() == 0) continue;
                int a = height[i] - height[now];
                int b = height[s.top()] - height[now];
                ans += (i - s.top() - 1) * min(a, b);
            }
            s.push(i);
        }
        return ans;
    }
};

你可能感兴趣的:(算法,数据结构,leetcode,c++)