笔记:代码随想录算法训练营day55:LeetCode42. 接雨水、84.柱状图中最大的矩形

学习资料:代码随想录

42. 接雨水

力扣题目链接

暴力解法超时了,直接从双指针开始

双指大概思路为创立两个数组记录两侧的最大值,这里的最大值是真正的最大的值,而不是最近的那个比较大的值,即所谓的按列计算,后面单调栈方法找到的是上一个较大值和下一个较大值,是所谓的按行计算,这样这个凹槽可能身处更大的凹槽中,所以每次都要乘一个宽度,类似与按层往上摞

class Solution {
public:
    int trap(vector& height) {
        vector Rightmax(height.size(),0);       //牺牲一点空间复杂度换时间复杂度
        vector Leftmax(height.size(),0);
        
        int size=height.size();

        Leftmax[0]=height[0];
        Rightmax[size-1]=height[size-1];

        for(int i=1;i=0;j--){
            Rightmax[j]=max(Rightmax[j+1],height[j]);
        }
        int sum = 0;
        for(int i=1;i0) sum+=capacity;
        }
        return sum;
    }
};

单调栈:遇到比栈顶小的值和等于的值就入栈,相当于等待那个大的出现,如次栈顶的下一个下标对应的值比它大,再遇到大的,正好栈顶元素的两边会比其大

要注意警惕对栈非空的判断,否则超时很难排查

class Solution {
public:
    int trap(vector& height) {
        stack st;
        st.push(0);

        int sum = 0;

        for(int i=1;iheight[st.top()]){
                    int cur = st.top();
                    st.pop();
                    if(!st.empty()){        //这里还要检查一下防止访问空
                        int h =min(height[i],height[st.top()])-height[cur];
                        int w=i-st.top()-1;
                        int capacity = h*w;
                        sum+=capacity;
                    }
                }
                st.push(i);
            }
        }
        return sum;
    }
};

84.柱状图中最大的矩形

力扣题目链接

先看单调栈的方法:首先要理解求这个面积的方法是当前的值为高,宽为左边比其小到右边比其小的这个距离,高乘宽为能勾勒的最大矩形的面积

这次是找两边的小值,逻辑上是接雨水变一下操作逻辑,当前大于等于栈顶的情况入栈,等那个小的,这样栈顶两侧都比其小

尾加一个0是为了数组最后是升序的情况下,让数组到最后能找到那个小的,进行计算逻辑。最后这个0会被放在栈里,不会影响结果

开头加一个0是为了在数组降序的情况下,能找到那个小的,能进行正常的计算逻辑

class Solution {
public:
    int largestRectangleArea(vector& heights) {
        stack st;
        st.push(0);

        heights.insert(heights.begin(),0);
        heights.insert(heights.end(),0);

        int result =0;

        for(int i=1;iheights[st.top()]){      //找的是比栈中元素小的
                st.push(i);
            }
            else if(heights[i]==heights[st.top()]){
                st.push(i);
            }
            else{
                while(!st.empty()&&heights[i]

这次双指针也是记录的下标了,而且和上一题不同的一个地方是,不是找两侧的最小的,而是找到第一个比其小的就停

// leftMinIndex[i]表示i处左边的较小高度柱子的高度的下标
class Solution {
public:
    int largestRectangleArea(vector& heights) {
        vector leftMinIndex(heights.size());
        vector rightMinIndex(heights.size());

        int result =0;
        
        leftMinIndex[0] = -1;    //初始化防止死循环
        for(int i=1;i=0&&heights[t]>=heights[i]){
                t=leftMinIndex[t];               //有回溯的感觉了
            }
            leftMinIndex[i]=t;
        }
        rightMinIndex[heights.size()-1] = heights.size(); //初始化防止死循环
        for(int j=heights.size()-2;j>=0;j--){
            int t=j+1;
            while(t=heights[j]){
                t=rightMinIndex[t];
            }
            rightMinIndex[j]=t;
        }
        
        for(int i=0;i

你可能感兴趣的:(算法)