[LeetCode] 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.

 

思路:

动态规划:

f[i][j] 表示在第i行中以(i,j)点结束点的前面有多少个连续的1,就是用f[i][j]来记录i行以j列为结尾,往前连续的1的个数。

然后用O(n^3)的循环来找以(i, j)为右下角的矩形最大的矩形的面积。

 

 

 

例如数组为

0  0  1

1  1  1

0  1  1

那么f数组为

0  0  1

1  2  3

0  1  2

在计算f[i][j]时使用的是一维动态规划

 

计算(i, j)为右下角的矩形最大的矩形的面积时,就是就去第0行到i行中以j结尾矩形的最大值,就是之前求过的 Largest Rectangle in Histogram

相当于是每一列,求一次Largest Rectangle in Histogram,然后求其所有列的最大值。。

 

方法一: O(n^3)

转载 http://www.cnblogs.com/remlostime/archive/2012/11/12/2766566.html

 1 class Solution {
 2     private:
 3         int f[1000][1000];
 4     public:
 5         int maximalRectangle(vector<vector<char> > &matrix) {
 6             // Start typing your C/C++ solution below
 7             // DO NOT write int main() function
 8             for(int i = 0; i < matrix.size(); i++)
 9                 f[i][0] = matrix[i][0] == '1' ? 1 : 0;
10 
11             for(int i = 0; i < matrix.size(); i++)
12                 for(int j = 1; j < matrix[i].size(); j++)
13                     f[i][j] = matrix[i][j] == '1' ? f[i][j-1] + 1 : 0;
14 
15             int ret = 0;
16             for(int i = 0; i < matrix.size(); i++)
17             {
18                 for(int j = 0; j < matrix[i].size(); j++)
19                 {
20                     int wid = INT_MAX;
21                     for(int k = i; k >=0; k--)
22                     {
23                         if(f[i][j] == 0)
24                             break;
25                         wid = min(wid, f[k][j]);
26                         ret = max(ret, wid* (i-k +1));
27                     }
28 
29                 }
30             }
31             return ret;
32 
33         }
34 };

 方法二,基于largestRectangleArea

将matrxi看出n行,求出每行的高度,然后调用largestRectangleArea

求解每行的高度的时候,使用的动态规划方法和方法一类似,

f[i][j]表示第i列中以(i,j)为结束连续1的个数

重点是

if(matrix[i][j] == '1')
f[i][j] = f[i-1][j] + 1;
else
f[i][j] = 0;

 共n行,每行调用largestRectangleArea的复杂度为O(n),所以是O(n^2),空间复杂度由于有矩阵f的存在,也是O(n^2)

 1 class Solution
 2 {
 3     public:
 4         int largestRectangleArea(vector<int> &height) {
 5 
 6             //add 0 to the end
 7             height.push_back(0);
 8 
 9             int size = height.size(); //this new_size is 1 + old_size
10             stack<int> st;
11 
12             int max_area = 0;
13 
14 
15 
16             for(int i = 0; i< size; )
17             {
18                 if(st.empty() || height[i] > height[st.top()])
19                 {
20                     st.push(i);
21                     i++;
22                 }
23                 else
24                 {
25                     //st must be not empty here
26                     // i can't ++; handle many times perhaps
27 
28                     int idx = st.top();
29                     st.pop();
30 
31                     int area;
32 
33                     if(st.empty())
34                     {
35                         area = height[idx] * i;
36                     }
37                     else
38                     {
39                         area = height[idx] * (i-st.top()-1);
40                     }
41 
42                     max_area = max(max_area, area);
43 
44                 }
45             }
46             return max_area;
47         }
48 
49         int maximalRectangle(vector<vector<char> > &matrix)
50         {
51             if(matrix.empty() || matrix[0].empty())
52                 return 0;
53             size_t row = matrix.size();
54             size_t col = matrix[0].size();
55 
56             //construct matrix f;
57             vector<vector<int> > f(row);
58             vector<int> array;
59             array.resize(col, 0);
60 
61             for(int i = 0; i < row; i++)
62                 f[i] = array;
63 
64             // initial f[0], the first row
65             for(int j = 0; j < col; j++)
66             {
67                 if(matrix[0][j] == '1')
68                     f[0][j] = 1;
69                 else
70                     f[0][j] = 0;
71             }
72 
73             for(int i = 1; i < row; i++)
74             {
75                 for(int j = 0; j < col; j++)
76                 {
77                     if(matrix[i][j] == '1')
78                         f[i][j] = f[i-1][j] + 1;
79                     else
80                         f[i][j] = 0;
81                 }
82             }
83 
84             int ret = 0;
85             for(int i = 0; i < row; i++)
86             {
87 
88                 ret = max(ret, largestRectangleArea(f[i]));
89             }
90 
91             return ret;
92 
93         }
94 } ;

 适当的优化:

  由于f[i][j] = f[i-1][j] + 1;的关系,二期在计算第i行时,第i-1行的数据有用,再之前的数据就没有了,所以我么可以不用保留整个col*row的矩阵,而只用一个数组就够了

  空间复杂度O(n),时间复杂度还是O(n^2)

 1 class Solution
 2 {
 3     public:
 4         int largestRectangleArea(vector<int> &height) {
 5 
 6             //add 0 to the end
 7             height.push_back(0);
 8 
 9             int size = height.size(); //this new_size is 1 + old_size
10             stack<int> st;
11 
12             int max_area = 0;
13 
14 
15 
16             for(int i = 0; i< size; )
17             {
18                 if(st.empty() || height[i] > height[st.top()])
19                 {
20                     st.push(i);
21                     i++;
22                 }
23                 else
24                 {
25                     //st must be not empty here
26                     // i can't ++; handle many times perhaps
27 
28                     int idx = st.top();
29                     st.pop();
30 
31                     int area;
32 
33                     if(st.empty())
34                     {
35                         area = height[idx] * i;
36                     }
37                     else
38                     {
39                         area = height[idx] * (i-st.top()-1);
40                     }
41 
42                     max_area = max(max_area, area);
43 
44                 }
45             }
46             return max_area;
47         }
48 
49         int maximalRectangle(vector<vector<char> > &matrix)
50         {
51             if(matrix.empty() || matrix[0].empty())
52                 return 0;
53             size_t row = matrix.size();
54             size_t col = matrix[0].size();
55 
56             vector<int> f;
57             f.resize(col, 0);
58 
59             int ret = 0;
60             for(int i = 0; i < row; i++)
61             {
62                 // update f
63                 for(int j = 0; j < col; j++)
64                 {
65                     // the first row 
66                     if(i == 0)
67                     {
68                         if(matrix[0][j] == '1')
69                             f[j] = 1;
70                         else
71                             f[j] = 0;
72                     }
73                     // other rows
74                     else
75                     {
76                         if(matrix[i][j] == '1')
77                             f[j] = f[j] + 1;
78                         else
79                             f[j] = 0;
80                     }
81                 }
82 
83                 ret = max(ret, largestRectangleArea(f));
84             }
85 
86             return ret;
87 
88         }
89 } ;

 

posted @ 2014-07-04 10:36  穆穆兔兔  阅读(213)  评论(0编辑  收藏  举报