問題:一個矩陣只含有0 1兩種元素,求只包含1的最大子矩陣大小(大小用包含的1的個數表示)
假設矩陣大小爲N x M, 要求時間複雜度爲O(N x M)
例如給定如下矩陣:
1 0 1 0 0
1 0 1 1 1
1 1 1 1 1
1 0 0 1 0
Return 6
1 1 1 1 1
1 0 0 1 0
Return 5
1 0 1 0 0
1 0 1 1 1
Return 3
解
這個問題和求直方圖最大矩陣面積類似。將矩陣從第一行開始,把每列的元素加起來,存在arr數組中,新加入的元素如果爲0直接爲0,把得到的數組求直方圖最大矩陣面積。
例:用數組arr來記錄
1 0 1 0 0
1 0 1 1 1
1 1 1 1 1
1 0 0 1 0
第一行對應arr爲1 0 1 0 0求得最大直方圖最大矩陣面積爲1。
加上第二行arr變爲2 0 2 1 1 求得最大直方圖最大矩陣面積爲3。
加上第三行變爲3 1 2 2 2 求得最大直方圖最大矩陣面積爲6。
加上第四行變爲4 1 0 3 0 求得最大直方圖最大矩陣面積爲4。
最終結果爲6
//直方圖面積
int maxarea(vector<int>&obj){
stack<list<int>>help;
int ret = 0;
for (int i = 0; i < obj.size(); i++){
while (!help.empty() && obj[i] < obj[help.top().back()]){
int temp = help.top().front();
help.pop();
int left = help.empty() ? -1 : help.top().back();
int ret_temp = obj[temp] * (i - left - 1);
ret = ret>ret_temp ? ret : ret_temp;
}
if (!help.empty()&&obj[i] < obj[help.top().back()])
help.top().push_back(i);
else{
list<int>l;
l.push_back(i);
help.push(l);
}
}
while (!help.empty()){
int temp = help.top().front();
help.pop();
int left = help.empty() ? -1 : help.top().back();
int ret_temp = obj[temp] * (obj.size() - left - 1);
ret = ret>ret_temp ? ret : ret_temp;
}
return ret;
}
//arr的變化
vector<int>& getarr(vector<int>&help, vector<vector<int>>&obj, int i){
for (int j = 0; j < obj[0].size(); j++){
help[j] = obj[i][j] == 0 ? 0 : help[j] + obj[i][j];
}
return help;
}
//求最大子矩陣
int maxrec(vector<vector<int>>&obj){
vector<int>help(obj[0].size(),0);
int ret = 0;
for (int i = 0; i < obj.size(); i++){
//arr的變化
getarr(help, obj, i);
//求直方圖面積
int temp = maxarea(help);
ret = ret>temp ? ret : temp;
}
return ret;
}