Leetcode84和85新开一个吧,属于单调栈但是更多是一种思想吧,就是设计柱状图的时候都有类似的思想,还有就是思想的一系列流程

Leetcode84 柱状图中的最大矩形
在这里插入图片描述
在这里插入图片描述
方法1:暴力法,就是找每个高度,连续的个数即可
未改进的暴力法用时:646ms,打败5.05

class Solution {
    public int largestRectangleArea(int[] heights) {
        Map<Integer,Integer> map=new HashMap();//存放高度以及对应,节省时间的
        int res=0;
        for(int i=0;i<heights.length;i++){
            if(map.containsKey(heights[i])){
                continue;
            }
            int count=0;
            int max=0;
            for(int j=0;j<heights.length;j++){
                if(heights[j]<heights[i]){
                    max=Math.max(count,max);
                    count=0;
                    continue;
                }
                count++;
            }
            max=Math.max(count,max);
            res=Math.max(res,max*heights[i]);
        }
        return res;
    }
}

暴力改进,就是相同高度的,不去球了,woca 我擦 为啥时间又多了呢,我估计是map耗时了,改成数组应该会好很多。。反正用map时间居然更长了。。大概是840ms左右

class Solution {
    public int largestRectangleArea(int[] heights) {
        Map<Integer,Integer> map=new HashMap();//存放高度以及对应,节省时间的
        int res=0;
        for(int i=0;i<heights.length;i++){
            if(map.containsKey(heights[i])){
                continue;
            }
            int count=0;
            int max=0;
            for(int j=0;j<heights.length;j++){
                if(heights[j]<heights[i]){
                    max=Math.max(count,max);
                    count=0;
                    continue;
                }
                count++;
            }
            max=Math.max(count,max);
            map.put(heights[i],1);
            res=Math.max(res,max*heights[i]);
        }
        return res;
    }
}

类似于快排那种方法我还没有写,因为那个思路还不会,等会了再说吧,力扣里面的解析已经讲解的很好了,可以直接参考。
方法2:预处理两个数组,左边最小值数组和右边最小值数组,这个和单调栈类似,但是效率应该会高不少,虽然都是on时间复杂度,但是这个不用栈,此方法时间是2ms,击败99的用户

纠正我上面说的,我说错了,因为用栈的话不需要左右最小值数组,只需要两个变量即可了

class Solution {
    public int largestRectangleArea(int[] heights) {
        //每个元素左边第一个小于他的坐标数组:
        if(heights.length==0||heights==null){
            return 0;
        }
        int [] leftFirstMin=new int[heights.length];
        leftFirstMin[0]=-1;
        for(int i=1;i<heights.length;i++){
            if(heights[i]>heights[i-1]){
                leftFirstMin[i]=i-1;
                continue;
            }
            int j=i-1;
            while(j!=-1&&heights[j]>=heights[i]){
                j=leftFirstMin[j];
            }
            leftFirstMin[i]=j;
        }
        //每个元素右边第一个小于他的数组:
        int[] rightFirstMin=new int[heights.length];
        rightFirstMin[heights.length-1]=heights.length;
        for(int i=heights.length-2;i>=0;i--){
            if(heights[i]>heights[i+1]){
                rightFirstMin[i]=i+1;
                continue;
            }
            int j=rightFirstMin[i+1];
            while(j!=heights.length&&heights[j]>=heights[i]){
                j=rightFirstMin[j];
            }
            rightFirstMin[i]=j;
        }
        //至此,左右两个数组都已经求出来了,接下来就是遍历每个柱子,然后计算面积
        int res=0;
        int area=0;
        for(int i=0;i<heights.length;i++){
            area=heights[i]*(rightFirstMin[i]-leftFirstMin[i]-1);
            res=Math.max(res,area);
        }
        return res;
    }
}

方法3,单调栈,果然用栈速度就是慢,也就是说相同复杂度的时候一定最好用基础结构吗,反正花了12ms
这里有一点注意,左神说,对于相等的处理可以用个list(栈存list)来存,这样可以得到正确的左边最小值和右边最小值,这个很重要,但是这个题你注意,如果我不这样做也不影响结果的,因为相同值中最大那个一定是正确的,而错误的一定是小的,所以我可以不用list,但是正常一定要用不能图意省事哦,这个题是个例,只限于这个题可以不用,记住 !!!! 记住!!!!!记住!!!!相同值单调栈的处理一定要记住!!!!!

class Solution {
    public int largestRectangleArea(int[] heights) {
        Stack<Integer> st=new Stack();
        int res=0;
        for(int i=0;i<heights.length;i++){
            while(!st.isEmpty()&&heights[st.peek()]>heights[i]){
                int height=heights[st.pop()];
                int leftmin=-1;
                if(!st.isEmpty()){
                    leftmin=st.peek();
                }
                int area=(i-leftmin-1)*height;
                res=Math.max(res,area);
            }
            st.push(i);
        }
        while(!st.isEmpty()){
            int height=heights[st.pop()];
            int rightmin=heights.length;
            int leftmin=-1;
            if(!st.isEmpty()){
                leftmin=st.peek();
            }
            int area=(rightmin-leftmin-1)*height;
            res=Math.max(area,res);
        }
        return res;
    }
}

大总结::数组可以模拟单调栈,而且速度提升不少,7倍哦,所以,你懂的,想秀操作不,想在面试场秀操作不,请用单调栈魔板,你用数组写bug free怕是不太现实把,老实用魔板。。。

leetcode 85(hard hard 这个是有点难了(除了暴力那个方法哈))
在这里插入图片描述
方法1:暴力法,但是还是有一些技巧的,有:1。数组预处理,这个就很重要,前面很多题,通过数组预处理,可以大大简化过程,这个太重要。2。边界问题,怎么做到0 bug 我写第一遍大概只出了一处错误(非边界错误,变量错误),这就是刷题的好处,刷的越多,对边界越可以控制的更好,这个只能刷题,只有这一个办法,别无他法。
过程:其实就是求每个 高度可能的1的最大值,遍历每个高度,遍历只需要沿着当前列向上遍历(因为我数组预处理的是从当前节点,左边到当前节点连续1的个数,如果你做了的不是这个预处理,那么会有一点不同)

class Solution {
    public int maximalRectangle(char[][] matrix) {
        if(matrix.length==0||matrix[0].length==0){
            return 0;
        }
        int[][] help=new int[matrix.length][matrix[0].length];
        //初始化数组,就是每一行连续1的个数
        for(int i=0;i<matrix.length;i++){
            int count=0;
            for(int j=0;j<matrix[0].length;j++){
                if(matrix[i][j]=='1'){
                    count++;
                    help[i][j]=count;
                }else{
                    count=0;
                }
            }
        }
        //预处理数组已经完事
        int res=0;
        for(int i=0;i<matrix.length;i++){
            for(int j=0;j<matrix[0].length;j++){
                int i1=i;//这里出错了,如果用i,那不是sb。。我就是
                int min=help[i1][j];
                int height=1;
                while(i1>=0&&help[i1][j]!=0){
                    min=Math.min(min,help[i1][j]);
                    int area=min*height;
                    res=Math.max(res,area);
                    height++;
                    i1--;
                }
            }
        }
        return res;
    }
}

方法2:参看leetcode把emmmm

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值