最大矩阵

博客探讨如何在柱状统计图中找到最大的矩形面积,利用直方图的特点,通过寻找上升序列来确定可能的左边界,并在遇到高度下降时检查栈中的右边界,从而计算最大矩阵。此外,还提到了该方法可应用于寻找矩阵中的最大0-聚类或1-聚类问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

给一个柱状统计图,各个小矩形宽度相等,高度不一,每一个矩形是由几个相邻柱状条条组成,矩形的高度为最短的那根条条,求所有组合中最大的矩形面积,假设柱状统计图是放在数组里的,数组记录的是每个条条的高度。


http://zhangzhibiao02005.blog.163.com/blog/static/3736782020118433623459/

在直方图中,一个长方形由其左边界和右边界决定,其最大可能的高度由两者中的最小者决定。记 R(i,j) 为由第 i 个直方柱为左边界,第 j 个直方柱确定的面积最大的长方形。如果 R(i,j) 的面积最大,那么,第 i 个直方柱比它的前一个直方柱(如果存在的话),即第 i-1 个直方柱要高,而 第 j 个直方柱的高度也比第 j+1 个的要高,否则,由 R(i,j+1) 或 R(i-1,j) 的面积比 R(i,j) 还要大,这违背了 R(i,j) 的最优性。根据这个观察,我们从第1个直方柱开始,寻找第一个 i, 使得直方柱 i 的高度比 i+1 的大,则 i 是一个可能的右边界,而 i 之前的每一根直方柱都是可能是左边界(因为 i 是第一个比 i + 1 高的直方柱,所以,在 i 之前的是一个上升的直方柱序列,每一根都比前一根要高)。这时,我们计算前面所有可能的长方形的面积,并跟当前已知的最大值进行比较,并更新当前已知的最大值(如有必要的话)。然后,我们继续向前搜索第二个这样的 i 。重复这个过程,直到最后一根直方柱。


设R(i, j)是最大矩阵的左右边界,那么height[j] > height[j +1], height[i] > height[i-1]

所以一旦遇到高度小于当前栈顶元素时,就有可能有最大矩阵,这时候就要从栈中不断的弹出

int maxRec(int a[], int n) {
    if (n == 0)
        return 0;
    stack<Node> sk;
    int rst = 0;
    sk.push(Node(0,a[0]));
    for(int i = 1; i < n; ++i ) {
        if(a[i] >= sk.top().height)
            sk.push(Node(i,a[i]));
        else {
            Node last = sk.top();
            while (!sk.empty() && sk.top().height > a[i])
            {
                Node t = sk.top();
                sk.pop();
                int rec = (last.index - t.index + 1) * t.height;
                if (rst < rec)
                    rst = rec;

            }

            sk.push(Node(i,a[i]));
        }
    }

    Node last = sk.top();
    while (!sk.empty()) {
        Node t = sk.top();
        sk.pop();
        int rec = (last.index - t.index + 1) * t.height;
        if(rst < rec)
            rst = rec;
    }

    return rst;
}


对于这一题:

 有一个 m x n 的矩阵,元素为 0 或 1。一个子矩阵,如果它所有的元素都是 0, 或者都是 1,则称其为一个 0-聚类 或 1-聚类,统称聚类(Cluster)。请找出最大的聚类(元素最多的聚类)。(问题来源:某面试题)


可以用之前所讲的dp做:http://blog.youkuaiyun.com/sunmenggmail/article/details/7709004

也可以用直方图最大矩阵做。

一行一行处理,每一行把0的高度看做是直方图,然后求出这一行的最大矩阵


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值