[leetcode] Maximal Rectangle


Maximal Rectangle

Given a 2D binary matrix filled with 0’s and 1’s, find the largest rectangle containing all ones and return its area.

tags: array, stack, hash table, dynamic programming

很烦leetcode的一点就是,大部分题都不给时间复杂度和空间复杂度的要求。还得自己一点点来试。

这也是我见到的tag最多的一题,难度也为hard。

先写了暴力的O(nm)^2的算法,超时。

版本一:暴力搜索,O((nm)^2)。超时

class Solution {
public:
/**
 * assume the size of 2D array is n*m.
 * this is a brute violent algorithm with the O((nm)^2) time complexity.
 * **/
 
    int maximalRectangle(vector<vector<char> > &matrix) {
        //handle empty input
        if(matrix.empty()){
            return 0;
        }
        
        int maxArea = 0;
        int height = matrix.size();
        int length = matrix[0].size();
        
        //(sx, sy) is the left-top corner of a possible rectangle 
        for(int sy = 0; sy < height; sy++){
            for(int sx = 0; sx < length; sx++){
                if(matrix[sy][sx] == '1'){
                    
                    //(x,y) is the right-bottom corner of a possible rectangle
                    int maxLength = length;
                    for(int y = sy; y < height; y++){
                        for(int x = sx; x < length; x++){
                            if(matrix[y][x] == '0' || x - sx + 1 == maxLength){
                                
                                //update maxLength
                                maxLength = x - sx + 1;
                                int thisArea = (x - sx + 1) * (y - sy + 1);
                                maxArea = max(maxArea, thisArea);
                            }
                        }
                    }
                }
            }
        }
    
        return maxArea;
    }
};

我想写分治算法的,就是分别求出子区域的最大矩形面积,然后再求邻接边界的最大矩形面积,再拼出一个跨边界的矩形,算三者的最大值。但感觉很麻烦,尤其是拼矩形时的算法。

看了discussion,有人晒出了O(nm)的代码。利用了stack,并压缩了原始矩阵,还在学习中,稍候更新。

一月二十四日更新

版本二:o(mn). 动态规划,栈。

这个版本有点奇技淫巧。不够clean,但是能AC,还在尝试优化。

新建一个与原题一样大小的矩阵,每个单元格表示,从包括该单元格开始向上查的连续的1的个数。

也就是变成了矩形高度的直方图。

1010        1010
1011    =>  2021
1011    =>  3032
1111        4143

建完该矩阵后,开始扫每一行。并维护一个栈。栈里存储的是,可能的最大矩形的左下角的位置。算法保证了栈中的元素是递增的。当扫到每行的末尾时,计算栈里每个元素代表的矩阵大小,把栈清空。

比较难理解,这个方法不够清晰。尝试优化中。

更新:

原来这个是有特定算法的。求直方图中的最大面积:

http://blog.csdn.net/havenoidea/article/details/11854723

那这个算法就不算是奇技淫巧了阿~~哇哈哈。AC

class Solution {
public:
/**
 * O(nm)
 **/
    int maximalRectangle(vector<vector<char> > &matrix) {
       
        if(matrix.empty()){
            return 0;
        }
        
        int height = matrix.size();
        int length = matrix[0].size();
        int maxArea = 0;
        //s stores possible left-bottom start corner. 
        stack<int> s;
        
        //map stores the current rectangle height of current column.
        int map[height][length];
        
        for(int i = 0; i < length; i++){
            map[0][i] = matrix[0][i] == '1'?1:0;
        }
        
        for(int j = 1; j < height; j++){
            for(int i = 0; i < length; i++){
                map[j][i] = matrix[j][i] == '1'?map[j - 1][i] + 1:0;
            }
        }
        
        for(int i = 0; i < height; i++){
            int j = 0;
            while(j != length){
                if(s.empty()){
                    s.push(j);
                    j++;
                }
                
                //s is not empty
                else{
                    if (map[i][j] >= map[i][s.top()]){
                        s.push(j);
                        j++;
                    }
                    //map[i][j] < the top of stack
                    else{
                        while(map[i][j] < map[i][s.top()]){
                            int t = s.top();
                            s.pop();
                            int start = s.empty()?-1:s.top();
                            int thisArea = map[i][t] * (j - start - 1);
                            maxArea = max(thisArea, maxArea);
                            if (s.empty()){
                                break;
                            }
                        }
                        //push j into the stack, now map[i][j] >= the top of stack 
                        
                        
                    }
                }
            }
            // j == length , at the end of the row
            while(!s.empty()){
                int t = s.top();
                s.pop();
                int start = s.empty()?-1:s.top();
                int thisArea = map[i][t] * (length - start - 1);
                maxArea = max(thisArea, maxArea);
            }
        }
        return maxArea;
    }
};

Selection_011

 

Leave a comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.