LeetCode Largest Rectangle in Histogram

题目大意

这题也是hdu 1506.
给定一个数组heights,其中heights[i]代表一个底为1,高为heights[i]的矩形。现在问你这个数组的所形成的“直方图”中最大的矩形面积。

思路

首先介绍一下单调队列单调栈。顾名思义,就是容器内元素是单调的。重点就是在将元素压入容器的时候需要保持容器内的有序性。
对于单调栈来说,一个很简单的应用是:求某一个元素左边(右边)比它大(小)的第一个元素。思路就是如果i < j && arr[i] > arr[j]那么对于j之后的元素来说,i就已经失去了意义(相当于把i从堆栈弹出去)。
对于单调队列来说,一个很简单的应用是求滑动窗口区间内的最值。因为窗口每滑动一次,只有一个数进入窗口,一个数离开窗口,因此可以用单调队列来维护。实现可以用stl的双端队列deque。


现在来看这道题,隐约觉得这道题既和数的大小有关,又和数的位置有关,因此觉得可以用单调栈来做。思考一下,如果从左往右考虑,有两个数arr[i]与arr[j],如果i < j 且 ar[i] > arr[j],那么对于j以后的数来说,arr[i]就失去了意义。此时就可以将arr[i]出栈。因此我要维护一个单调递增栈。那么面积怎么算呢?由于单调递增性质,假设当前位置为j,而栈顶元素为位置i,那么i到j-1之间的矩形高度一定都是大于j位置的高度的。如果不明白可以看代码,自己在纸上画一画就可以理解了。

class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        int res = 0, area = 0;
        stack<int> st;
        heights.push_back(0); //末尾添加一个0保证全部元素都出栈计算面积
        for (int i = 0; i < heights.size(); i++) {
            while (!st.empty() && heights[st.top()] >= heights[i]) {
                int cur = st.top(); st.pop();
                area = heights[cur] * (st.empty() ? i : i-1-st.top()); //好好想一下这个底的计算
                res = max(res, area);
            }
            st.push(i);
        }
        return res;

    }
};

Maximal Rectangle

Also Poj 3494
上一道题的延伸。这个最大的矩形怎么求呢?这样考虑:对于每一行来说,我把这一行每一列开始连续的1的个数看为高度,那么实际就是求Largest Rectangle in Histogram。我处理好数据之后对每一行都做一次,就得到了最终的Maximal Rectangle.

class Solution {
public:

    int sol(vector<int> heights) {
        int ans = 0;
        stack<int> st;
        for (int i = 0; i < heights.size(); i++) {
            while (!st.empty() && heights[st.top()] > heights[i]) {
                int cur = st.top(); st.pop();
                ans = max(ans, heights[cur] * (st.empty() ? i : i-st.top()-1));
            }
            st.push(i);
        }
        return ans;
    }

    int maximalRectangle(vector<vector<char>>& matrix) {
        if (matrix.size() == 0 || matrix[0].size() == 0) return 0;
        int m = matrix.size(), n = matrix[0].size(), res = 0;
        vector<int> heights(n+1, 0);
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (matrix[i][j] == '0') {
                    heights[j] = 0;
                } else
                    heights[j] = i == 0 ? 1 : heights[j]+1;
            }
            //先做好数据转换的工作。
            res = max(res, sol(heights));
        }
        return res;
    }
};

结语

两道感觉很不错的题目,一年前做过现在再来看早已经想不起来思路了,现在重新整理一遍思路。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值