LintCode 510: Maximal Rectangle (最大直方图题的变种,单调递增栈经典题)

  1. Maximal Rectangle
    Given a 2D boolean matrix filled with False and True, find the largest rectangle containing all True and return its area.

Example
Given a matrix:

[
[1, 1, 0, 0, 1],
[0, 1, 0, 0, 1],
[0, 0, 1, 1, 1],
[0, 0, 1, 1, 1],
[0, 0, 0, 0, 1]
]
return 6.

解法1:单调栈+矩阵累加和
构造一个新的矩阵height,值为matrix逐行累加。height的第一行即为matrix第一行,接下来如果height上下两行都>0 (下面一行最多为1,但上面一行可能>1),则将上行的值累加到下行。否则直接将matrix的对应行当下行。

接下来对height的每行求maximalRectangle(),然后求最大值即可。即这题是最大直方图矩形的变种。

代码如下:

class Solution {
public:
    /**
     * @param matrix: a boolean 2D matrix
     * @return: an integer
     */
    int maximalRectangle(vector<vector<bool>> &matrix) {
        int m = matrix.size();
        if (m == 0) return 0;
        int n = matrix[0].size();
        
        vector<vector<int>> height(m, vector<int>(n, 0));
        
        for (int i = 0; i < m; ++i) {
            for (int j = 0; j < n; ++j) {
                if ((i > 0) && (matrix[i][j] > 0) && (height[i - 1][j] > 0)){
                    height[i][j] = height[i - 1][j]  + matrix[i][j];
                } else {
                    height[i][j] = matrix[i][j];
                }
            }
        }
 
        int maxArea = 0;
        for (int i = 0; i < m; ++i) {
            maxArea = max(maxArea, maximalRectangle(height[i]));     
        }
        
        return maxArea;
    }
    
private:
    int maximalRectangle(vector<int> &nums) {
        int len = nums.size();
        if (len == 0) return 0;
        
        int maxArea = 0;
        vector<int> nums2 = nums;
        nums2.push_back(-1);

        stack<int> monoIncStack;

        for (int i = 0; i <= len; ++i) {
            while (!monoIncStack.empty() && (nums2[i] < nums[monoIncStack.top()])) {
                int top = monoIncStack.top();
                monoIncStack.pop();
                int h = nums2[top];
                int w = monoIncStack.empty() ? i : i - monoIncStack.top() - 1;  //not w = i - top - 1
                maxArea = max(maxArea, h * w);        
            }
            monoIncStack.push(i);
        }
        return maxArea;
    }
};

2刷:2维数组可以简化为1维数组

class Solution {
public:
    /**
     * @param matrix: a boolean 2D matrix
     * @return: an integer
     */
    int maximalRectangle(vector<vector<bool>> &matrix) {
        int m = matrix.size();
        if (m == 0) return 0;
        int n = matrix[0].size();
        int maxArea = 0;        

        vector<int> height(n, 0);
        
        for (int i = 0; i < m; ++i) {
            for (int j = 0; j < n; ++j) {
                if ((i > 0) && (matrix[i][j] > 0) && (height[j] > 0)){
                    height[j] += matrix[i][j];
                } else {
                    height[j] = matrix[i][j];
                }
            }
            maxArea = max(maxArea, maximalRectangle(height));     
        }

        return maxArea;
    }
    
private:
    int maximalRectangle(vector<int> &nums) {
        int len = nums.size();
        if (len == 0) return 0;
        
        int maxArea = 0;
        vector<int> nums2 = nums;
        nums2.push_back(-1);

        stack<int> monoIncStack;

        for (int i = 0; i <= len; ++i) {
            while (!monoIncStack.empty() && (nums2[i] < nums[monoIncStack.top()])) {
                int top = monoIncStack.top();
                monoIncStack.pop();
                int h = nums2[top];
                int w = monoIncStack.empty() ? i : i - monoIncStack.top() - 1;  //not w = i - top - 1
                maxArea = max(maxArea, h * w);        
            }
            monoIncStack.push(i);
        }
        return maxArea;
    }
};

注意,这题不要跟Leetcode 221 Maximal square 混淆。那题是求最大正方形,这题是求最大矩形。
Leetcode 221 那题要用DP做。

Leetcode 221 Maximal Square
Given a 2D binary matrix filled with 0’s and 1’s, find the largest square containing only 1’s and return its area.

Example:

Input:

1 0 1 0 0
1 0 1 1 1
1 1 1 1 1
1 0 0 1 0

Output: 4

class Solution {
public:
    int maximalSquare(vector<vector<char>>& matrix) {  
     if(matrix.size() == 0) return 0;  
       
     int row = matrix.size();  
     int col = matrix[0].size();  
     vector<vector<int>> dp(row+1, vector<int>(col+1, 0));  
       
    int maxLen = 0;  
    for(int i =1; i<=row; i++) {  
       for(int j =1; j<= col; j++) {  
         if(matrix[i-1][j-1] == '1') {  
            dp[i][j] = min(min(dp[i-1][j-1], dp[i-1][j]), dp[i][j-1])+1 ;  
           maxLen = max(maxLen, dp[i][j]);  
          }  
       }  
     }  
    return maxLen*maxLen;  
  }  
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值