单调栈问题#柱状图#接雨水#每日温度

单调栈的好处:及时去掉无用数据,保持栈内数据有序。

单调栈就是在数组中寻找下个更大(更小)的元素(咱们记录到栈里的都是下标,因为下标有更好的映射关系)。

84、柱状图中最大的矩形

写代码前先使用暴力方法解决问题,如果不能解决的话再去优化算法,使用其他方法。

我们最先想到的就是枚举这一种方法,把所有情况全部计算出来,再去寻找最好的一种结果。

1.枚举方法(出现超时现象)

class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
            int n=heights.size();
            int ans=0;
            for(int i=0;i<n;i++){
                int mh=INT_MAX;
                for(int j=i;j<n;j++){
                    mh=min(mh,heights[j]);//我们只能选最低的做高,在向后的遍历时,我们必须找到一个最低的高 枚举
                    ans=max(ans,(j-i+1)*mh);
                }
            }
            return ans;
    }
};

2.单调栈

class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
            int n=heights.size();
            vector<int> left(n),right(n);
            int ans=0;
            stack<int> s;
        	//left数组 存的是每个数据左边的最近的最小值
            for(int i=0;i<n;i++){
                while(!s.empty()&&heights[s.top()]>=heights[i]){
                    s.pop();
                }//因为第一个数的左边没有数据,所以left[0]=-1
                // -1表示左边没有比当前数据还 小 的值
                left[i]=s.empty()?-1:s.top();//注意
                s.push(i);
            }
	        //right数组 存的是每个数据右边的最近的最小值
            s=stack<int>();//栈的初始化,必须记住,  = stack();
        
            for(int i=n-1;i>=0;i--){ //从后向前去寻找每个数据右边的第一个最小的值是啥
                while(!s.empty()&&heights[s.top()]>=heights[i]){
                    s.pop();
                }
                right[i]=s.empty()?n:s.top();//注意
                s.push(i);
            }
            for(int i=0;i<n;i++){
                ans=max(ans,(right[i]-left[i]-1)*heights[i]);
            }
            return ans;
    }
};

42、接雨水

接雨水的话,一般都是以低的为准。

我们可以使用两个数组来计算前缀最高的木板,定义两个数组pre_max、nex_max分别计算前缀的最大高度以及后缀的最大高

那么这两个中最小的值 减去 本位置的高就是他的容量。

1.动态规划(使用数组,存储计算过的数据)

class Solution {
public:
    int trap(vector<int>& height) {
        int n=height.size();
        vector<int> pre_max(n),nex_max(n);

        pre_max[0]=height[0];
        for(int i=1;i<n;i++){
            pre_max[i]=max(pre_max[i-1],height[i]);
        }

        nex_max[n-1]=height[n-1];
        for(int i=n-2;i>=0;i--){
            nex_max[i]=max(nex_max[i+1],height[i]);
        }

        int ans=0;
        for(int i=0;i<n;i++){
            ans+=min(pre_max[i],nex_max[i])-height[i];
        }
        return ans;
    }
};

2.单调栈

class Solution {
public:
    int trap(vector<int>& height) {
        int n=height.size();
        stack<int> s;
        int ans=0;
        for(int i=0;i<n;i++){
            while(!s.empty()&&height[s.top()]<height[i]){
                int top=s.top();
                s.pop();
                if(s.empty())break;
                int left=s.top();
                int curWidth=i-left-1;
                int curHigh=min(height[left],height[i])-height[top];
                ans+=curHigh*curWidth;
            }
            s.push(i);
        }
        return ans;
    }
};

739、每日温度

我们使用从右向左的遍历方法,使用单调栈的思路。

class Solution {
public:
    vector<int> dailyTemperatures(vector<int>& temperatures) {
        int n=temperatures.size();
        vector<int> ans(n);
        stack<int> s;
        for(int i=n-1;i>=0;i--){
            //这里要小于号,就是因为我们已经出现了比cur还小的温度了,所以我们就要把它弹出栈,因为前面的元素比cur元素大,所以我们就不需要这个比较小的元素了
            while(!s.empty()&&temperatures[s.top()]<=temperatures[i]){
                s.pop();
            }
            ans[i]=s.empty()?0:s.top()-i;
            s.push(i);
        }
        return ans;
    }
};

你可能感兴趣的:(C/C++备战蓝桥杯,算法,c++,数据结构)