85. Maximal Rectangle
Problem statement:
Given a 2D binary matrix filled with 0's and 1's, find the largest rectangle containing only 1's and return its area.
For example, given the following matrix:
1 0 1 0 0 1 0 1 1 1 1 1 1 1 1 1 0 0 1 0
Return 6.
Solution one:
This is 2D dimension of 84. Largest Rectangle in Histogram, we could write a single function and call this function after updating the height of each row.
For the height in each row
height[j] = (matrix[i][j] == '1' ? height[j] + 1 : 0);
Since height only depends on it`s value and height[i - 1][j], we just one one dimension and update it in each row. This is a dynamic programming philosophy.
The time complexity is O(n * n).
class Solution { public: int maximalRectangle(vector<vector<char>> &matrix) { if(matrix.empty()){ return 0; } int row = matrix.size(); int col = matrix[0].size(); int max_area = 0; vector<int> heights(col, 0); for(int i = 0; i < row; i++){ for(int j = 0; j < col; j++){ heights[j] = (matrix[i][j] == '1' ? heights[j] + 1 : 0); } max_area = max(max_area, largestRectangleArea(heights)); } return max_area; } private: int largestRectangleArea(vector<int>& heights) { int max_area = 0; for(int i = 0; i < heights.size(); i++){ if(i + 1 < heights.size() && heights[i] <= heights[i + 1]){ continue; } else { // find a local maximum value // loop back to update max area int min_height = INT_MAX; int cur_area = 0; // loop back to find the update the max area for(int j = i; j >= 0; j--){ min_height = min(min_height, heights[j]); max_area = max(max_area, min_height * (i - j + 1)); } } } return max_area; } };
Solution two:
This solution is top ratted in leetcode discussion section. It also uses dynamic programming, keeps three array, left[n], right[n], height[n] to record the most left boundary, right boundary, and height of each element in a row. The max area based on current element is (right - left) * height.
The time complexity is O(n * n).
class Solution { public: int maximalRectangle(vector<vector<char>> &matrix) { if(matrix.empty()){ return 0; } int row = matrix.size(); int col = matrix[0].size(); vector<int> left(col, 0); vector<int> right(col, col); vector<int> height(col, 0); int max_area = 0; for(int i = 0; i < row; i++){ // update the left boundary int cur_left = 0; for(int j = 0; j < col; j++){ if(matrix[i][j] == '1'){ left[j] = max(left[j], cur_left); } else { left[j] = 0; cur_left = j + 1; } } // update the right boundary int cur_right = col; for(int j = col - 1; j >= 0; j--){ if(matrix[i][j] == '1'){ right[j] = min(right[j], cur_right); } else { right[j] = col; cur_right = j; } } // update the height and max area for(int j = 0; j < col; j++){ height[j] = (matrix[i][j] == '1' ? height[j] + 1 : 0); max_area = max(max_area, (right[j] - left[j]) * height[j]); } } return max_area; } };