1

1 Introduction

In a sharing a while ago, the data structure of the monotonic stack was briefly mentioned. The article is as follows↓↓↓

Share a simple but interesting algorithm problem 2-greedy-monotone stack-dynamic programming

At that time, I only solved the stock problem with the monotonic stack, which is the most basic entry example, which is easy or barely medium level, today I use the monotonic stack to solve some hard topic

2 Example - catch rain

42. Catch rain

This is a classic interview question. There are three solutions. One is forward and reverse traversal to find the left and right maximum height of each point, which is barely considered dynamic programming; the second is monotonic stack; the third is double pointer; the most efficient is double pointer, The lowest is the forward and reverse traversal. The efficiency of the monotonic stack is the same as that of the double pointer, but one more stack structure is used, so the space complexity is not optimal.

2.1 The idea of monotone stack

It is not difficult to imagine that the rainwater that each point can receive depends on the maximum height of the left and right sides of the point. The minimum value between the two is the maximum height of the rainwater. The forward and reverse traversal of method 1 is also to find the maximum height of the left and right sides. Height, the advantage is that it is intuitive and easy to understand, and the disadvantage is that it is traversed twice, which is less efficient.

If you think about it carefully, you can use a monotonic stack to maintain a decreasing monotonic stack, and you can also find the maximum height of the left and right sides of the point, but not for every point, but every uphill, as long as there is an uphill, it will pop up, and calculate rainwater;

The specific idea is: when an element smaller than the top of the stack is encountered, push it into the stack, and when an element larger than the top of the stack is encountered, and the stack is not empty at this time, the top of the stack is popped, and the calculated width is i - 已弹出的栈顶 - 1 , the height is min(height[i], 最新栈顶的高度) - 已弹出的栈顶

2.2 Code

 var trap = function(height) {
    let stack = [];
    let len   = height.length
    let res   = 0;
    for(let i=0;i < len;i++){
        while(stack.length > 0 && height[i] > height[stack[stack.length - 1]]){
            let top = height[stack.pop()]
            if(stack.length == 0){
                break
            }
            let width_ = i - stack[stack.length - 1] - 1
            let height_= Math.min(height[i], height[stack[stack.length - 1]]) - top
            res += width_*height_
        }
        stack.push(i)
    }
    return res
};

image.png

3 Example - Largest rectangle in a column chart

84. The largest rectangle in a bar chart

3.1 The idea of monotone stack

This is basically the same as the idea of the previous question, except that it is changed to maintain a monotonically increasing stack. When an element larger than the top of the stack is encountered, it is pushed into the stack. When an element smaller than the top of the stack is encountered, it means that the uphill is over and a pop-up is required.栈顶,计算最大面积了, 刚刚弹出的栈顶对应的高度 ,宽度i - 最新栈顶下标 - 1 (PS:宽度i - 刚刚弹出的栈顶对应的下标 ,因为heights[i] may be continuously smaller than 最新栈顶 , at this time, the width will be continuously widened horizontally)

3.2 Code

 var largestRectangleArea = function(heights) {
    heights.push(0)
    heights.unshift(0)
    let stack = []
    let len = heights.length
    let res = 0
    for(let i=0;i < len;i++){
        while(stack.length > 0 && heights[i] < heights[stack[stack.length - 1]]){
            //吐出来个
            let top_i  = stack.pop(stack)
            let height = heights[top_i]
            let width  = i - stack[stack.length - 1] - 1
            res = Math.max(res, height*width)
        }
        stack.push(i)
    }
    return res
};

image.png

4 Example - Largest Rectangle

85. Largest rectangle

4.1 Monotonic stack idea

This question is basically the same as the largest rectangle in the histogram. The largest rectangle in the histogram is calculated by one layer. This is the calculation of multiple layers. We treat each row as a histogram and find the maximum value of each layer. rectangle, where the maximum value is the final answer.

 matrix = [
    ["1","0","1","0","0"],
    ["1","0","1","1","1"],
    ["1","1","1","1","1"],
    ["1","0","0","1","0"]
]
//转化成柱状图后是
heights = [
    [ 1 , 0 , 1 , 0 , 0 ],
    [ 2 , 0 , 2 , 1 , 1 ],
    [ 3 , 1 , 3 , 2 , 2 ],
    [ 4 , 0 , 0 , 3 , 0 ]
]

heights traverse, find the largest rectangle of each row

4.2 Code

 var largestRectangleArea = function(heights) {
    heights.push(0)
    heights.unshift(0)
    let stack = []
    let len = heights.length
    let res = 0
    for(let i=0;i < len;i++){
        while(stack.length > 0 && heights[i] < heights[stack[stack.length - 1]]){
            //吐出来个
            let top_i  = stack.pop(stack)
            let height = heights[top_i]
            let weight = i - stack[stack.length - 1] - 1
            res = Math.max(res, height*weight)
        }
        stack.push(i)
    }
    return res
};
var maximalRectangle = function(matrix) {
    let h    = matrix.length
    let w    = matrix[0].length
    let tree = [];
    let res  = 0;
    for (let i = 0; i < h; i++) {
        tree[i] = new Array(w)
        for (let j = 0; j < w; j++) {
            //树的高度
            if (matrix[i][j] == '0') {
                tree[i][j] = 0
            }else{
                tree[i][j] = i > 0 ? tree[i-1][j] + 1 : 1
            }
        }
        let this_line = largestRectangleArea(tree[i].concat())//这里因为js的天生短板,要使用深拷贝
        res = Math.max(res, this_line)
    }
    return res
};

image.png


tfzh
231 声望17 粉丝

code what u love & love what u code