单调栈——求区间最小数乘区间和的最大值(单调增)

思路:

计算目标:计算以不同数作为区间最小数时,对应最大区间的(区间和*最小数)的值(因为最小数是固定的,最后要求的结果一定属于最小数*最大区间之和,因此找最大区间即可)。

数组元素依次入栈,当当前元素小于栈顶时,可以对栈顶元素作为最小数的情况进行计算(因为此时栈顶元素>其栈内前面的元素,且栈顶元素>当前元素,即栈顶元素作为最小数的区间范围可以确定:栈顶元素对应的下标~当前元素之前),对栈顶元素计算完之后,将其弹出,然后继续对栈顶元素进行判断。直到栈空。


类似的题目有:

接雨水:(单调递减栈):就是当遇到比栈顶元素大的元素时,将栈顶弹出,这时可以计算当前元素和新的栈顶之间的雨水,继续判断当前元素是否比栈顶元素小,如果是的话就弹出,如果栈空,则只把当前元素入栈,否则继续计算当前元素和新的栈顶之间的雨水)、

求最大矩形面积(单调递增栈):计算目标是“计算以不同列作为矩形高度的最大矩形的面积,即求以不同列作为最小数的区间范围”,因此当遇到比栈顶小的元素时,可以计算该范围(因为栈内单调增,可以保证前面的元素小于栈顶元素(且前面挨着的元素为栈顶元素在数组中向左的第一个比他小的元素,即中间的元素都比他大,因为他一定会将之前比他大的元素弹出栈,因此它在这个范围内为最小值),即可以确定区间左边界,当前元素是栈顶元素右边的第一个小于栈顶元素的元素否则栈顶不会在栈内),即栈顶元素到当前元素之间的元素都比栈顶大,可以确定区间右边界)

求区间最小数乘区间和的最大值(单调增)

题目描述

给定一个数组,要求选出一个区间, 使得该区间是所有区间中经过如下计算的值最大的一个:区间中的最小数 * 区间所有数的和。

数组中的元素都是非负数。

输入两行,第一行n表示数组长度,第二行为数组序列。输出最大值。

输入
3
6 2 1       3**3**28
输出
36
解释:满足条件区间是[6] = 6 * 6 = 36;

 代码如下(和最大矩形面积一样)。

技巧:前后设置哨兵(扩展数组,长度加2,高度均为0),前哨兵(1、作为最小左边界(如果栈内没有其他的比栈顶小的第一个元素的话,那么哨兵的位置+1=1即为最小左边界);2、减少非空判断,哨兵值为0,不会存在比0小的数组元素,因此栈不会为空,在进行取栈顶时不需要进行栈非空判断);后哨兵(当最后一个数组元素判断完之后,栈可能不为空,仍有其他待计算的列,而后哨兵高度为0,一定是小于栈顶元素的第一个元素,会触发对栈顶元素的计算,其右边界相当于后哨兵位置-1,即原数组最后一个元素的位置)

class Solution {
    public int largestRectangleArea(int[] heights) {
        Stack<Integer> stack=new Stack<Integer>();
        int[] newHeight=new int[heights.length+2];
        newHeight[0]=0;
        for(int i=0;i<heights.length;i++){
            newHeight[i+1]=heights[i];
        }
        newHeight[newHeight.length-1]=0;
        stack.add(0);
        int max=0;
        for(int i=1;i<newHeight.length;i++){
            //if(stack.isEmpty()) stack.push(i);
            while(newHeight[i]<newHeight[stack.peek()]){
                int cur=stack.pop();
                max=Math.max(max,newHeight[cur]*((i-1)-(stack.peek()+1)+1));
            }
            stack.push(i);
        }
        return max;
    }
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值