【Leetcode】单调栈问题--739.DailyTemperatures;769.MaxChunksToMakeSorted;84.LargestRectangleinHistogram;85

Desc: n/a


单调栈

定义;
能够解决的一类问题;



《程序员代码面试指南》CH1-栈与队列 – 单调栈结构

N/A



Leetcode#739. Daily Temperatures

N/A



Leetcode#769. Max Chunks To Make Sorted

N/A



Leetcode#?. Max Chunks To Make Sorted II

N/A



Leetcode#84. Largest Rectangle in Histogram

【描述】

Given n non-negative integers representing the histogram’s bar height where the width of each bar is 1, find the area of largest rectangle in the histogram.

n/a
Above is a histogram where width of each bar is 1, given height = [2,1,5,6,2,3].

n/a
The largest rectangle is shown in the shaded area, which has area = 10 unit.

【示例】

Input: [2,1,5,6,2,3]
Output: 10

【分析】

输入:上边界数组

过程:求出每个上边界的(能达到的最远)左右边界

实现:

  1. 遍历: O ( n 2 ) O(n^2) O(n2)
  2. 单调栈: O ( n ) O(n) O(n)

单调栈实现:

  1. 找出左边界的最近的比当前上边界小的位置(最近即能达到的最远)。
  2. 找出右边界的最近的比当前上边界小的位置。

得到每个 0,1,2,3,…,N-1 坐标的上边界高度对应的左右边界元组:

     [  2,     1,     5,    6,    2,    3  ]
index: 0    1      2     3      4    5     6(N)
     [(0,1), (0,6), (2,4),(3,4),(2,6),(5,6)]

输出: max ⁡ ( h e i g h t s [ i ] × ( b o r d e r [ i ] [ 1 ] − b o r d e r [ i ] [ 0 ] ) ) \max( heights[i] \times (border[i][1] - border[i][0]) ) max(heights[i]×(border[i][1]border[i][0]))

过程实现分析:

  1. 右边界:
    1. for r in range(len(heights))
    2. 递增,push index(r);
    3. 遇到小值,border[<pop index>][1] = r 直到大于 pop 的 index,然后 push;
    4. END 0->(N-1), while stack: border[<pop index>][1] = <N>
  2. 左边界:
    1. for l in range(len(heights) - 1, 0 - 1, -1)
    2. 递增,push index(l);
    3. 遇到小值,border[<pop index>][0] = l 直到大于 pop 的 index,然后 push;
    4. END (N-1)->0,while stack: border[<pop index>][0] = 0

Solution:

class Solution:
    def largestRectangleArea(self, heights: List[int]) -> int:
        if not heights: return 0
        # calculate the border here:
        border = [[-1, -1] for _ in range(len(heights))]
        stack = []
        # right ->->->
        for r, h in enumerate(heights):
            if not stack or h >= heights[stack[-1]]:  # h >= heights[.pick()]
                stack.append(r)  # push
            else:
                while stack and h < heights[stack[-1]]:  # h < heights[.pick()]
                    border[stack.pop()][1] = r
                stack.append(r)  # push
        while stack:
            border[stack.pop()][1] = len(heights)
        # left <-<-<-
        for l in range(len(heights)-1, 0-1, -1):
            h = heights[l]
            if not stack or h >= heights[stack[-1]]:
                stack.append(l)
            else:
                while stack and h < heights[stack[-1]]:
                    border[stack.pop()][0] = l + 1
                stack.append(l)
        while stack:
            border[stack.pop()][0] = 0
        return max([heights[i] * (border[i][1] - border[i][0]) for i in range(len(heights))])

Submission:

n/a



Leetcode#85. Maximal Rectangle

将 matrix 按行计算“高度”。即按行转化为 84. Largest Rectangle in Histogram 问题。

Solution:

class Solution:
    def maximalRectangle(self, matrix: List[List[str]]) -> int:
        if not matrix: return 0
        ans = []
        for row in range(len(matrix)-1, 0-1, -1):  # 0,1,2,...,(N-1)  # NxM
            heights = get_heights(matrix, row, len(matrix[row]))
            ans.append(self.largestRectangleArea(heights))
        return max(ans)

    def largestRectangleArea(self, heights: List[int]) -> int:
        # code 与 84. Largest Rectangle in Histogram 完全一致。

def get_heights(matrix, n, m):
    ans = []
    for _col in range(m):
        h = 0
        _row = n
        while matrix[_row][_col] == '1' and _row >= 0:
            h += 1
            _row -= 1
        ans.append(h)
    return ans

Submission:

n/a

注:
求 heights 数组应该使用 DP 的方式,可以优化一点速度!!!


na
上面的矩阵就成这样了:
n/a
每一行都是一次柱状图的最大矩形面积了。dp[i][j]就是当前的第j列到第i行连续1的个数。



相关数据结构与算法

  1. 【Leetcode】栈与队列(待更新 #)
  2. 【Leetcode】二叉树与二叉树遍历算法(递归和迭代方案)(待更新 #)
  3. 【Leetcode】二叉搜索树与二叉搜索树搜索算法、插入算法、删除算法 (待更新 #)
  4. 【Leetcode】最小堆、最大堆(待更新 #)
  5. 【Leetcode】N-Tree 与遍历算法(递归与迭代方案)(待更新 #)
  6. 【Leetcode】链表(待更新 #)
  7. 【Leetcode】图(待更新 #)

Reference

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值