add solution 5

This commit is contained in:
ShusenTang 2020-07-08 22:08:14 +08:00
parent 6f35069c39
commit af4b9b1bfc

View File

@ -39,6 +39,17 @@
时间复杂度O(n^2), 空间复杂度O(n)。
## 思路五、转换成求直方图包含的最大正方形
这题和[85. Maximal Rectangle](https://leetcode.com/problems/maximal-rectangle/)有点像不同点就是85题只需要矩形而本题要求区域是正方形。如果把二维矩阵的第 i 行及上面的部分可以看成是一个直方图那么85题又转化成了[84. Largest Rectangle in Histogram](https://leetcode.com/problems/largest-rectangle-in-histogram/)(见[85题思路一](85.%20Maximal%20Rectangle.md)。顺着这个思路我们也可以利用84题来解此题。
具体来说,我们把二维矩阵的第 i 行及上面的部分可以看成是一个直方图假设用数组hs表示然后采用[84思路一](84.%20Largest%20Rectangle%20in%20Histogram.md)求出直方图里包含的最大正方形:
求出`hs[i]`向左第一个比他小的数`hs[j1]`和向右第一个比他小的数`hs[j2]`。那么此时能容纳的正方形的边长就为高和宽的较小者,即`min(heights[i], j2 - j1 - 1)`。
求数组中每个元素的左边第一个比他大的元素可利用单调栈在O(n)时间内求出,关于单调栈可以参考[我的总结](../algorithm/array/monotonic_stack_queue.md)。
总的时间复杂度O(n^2), 空间复杂度O(n)。
## 思路一
``` C++
@ -157,3 +168,47 @@ public:
}
};
```
## 思路五
``` C++
class Solution {
private:
int helper(const vector<int>&hs){ // 求直方图能容纳的最大正方形, 类似84题
int n = hs.size(), max_l = 0;
vector<int>pre_smaller(n, -1), next_smaller(n, n); // 存的是下标
stack<int>stk1, stk2; // 存的也是下标
for(int i = 0; i < n; i++){
while(!stk1.empty() && hs[stk1.top()] >= hs[i]) stk1.pop();
if(!stk1.empty()) pre_smaller[i] = stk1.top();
stk1.push(i);
int j = n - i - 1; // 相当于反向遍历: for(int j = n-1; j >= 0; j--)
while(!stk2.empty() && hs[stk2.top()] >= hs[j]) stk2.pop();
if(!stk2.empty()) next_smaller[j] = stk2.top();
stk2.push(j);
}
for(int i = 0; i < n; i++)
max_l = max(max_l, min(hs[i], next_smaller[i] - pre_smaller[i] - 1));
return max_l * max_l;
}
public:
int maximalSquare(vector<vector<char>>& matrix) {
if(matrix.empty()) return 0;
int m = matrix.size(), n = matrix[0].size(), res = 0;
vector<int>hs(n, 0);
for(int i = 0; i < m; i++){
for(int j = 0; j < n; j++){
if(matrix[i][j] == '1') hs[j]++;
else hs[j] = 0;
}
res = max(res, helper(hs));
}
return res;
}
};
```