一、Problem
Given a 2D grid of 0s and 1s, return the number of elements in the largest square subgrid that has all 1s on its border, or 0 if such a subgrid doesn’t exist in the grid.
Example 1:
Input: grid = [[1,1,1],[1,0,1],[1,1,1]]
Output: 9
Example 2:
Input: grid = [[1,1,0,0]]
Output: 1
Constraints:
1 <= grid.length <= 100
1 <= grid[0].length <= 100
grid[i][j] is 0 or 1
二、Solution
方法一:暴力
- 題目讓你求全以 1 爲邊界的正方形的面積,那我們就只能枚舉邊界呀,還能怎麼做?
- 首先我們得固定一個起點 (正方形的左上、右上、左下、右下角都行)
- 然後再確定一個長度 ,從而構成一個正方形
- 最後檢查出該正方形的四條邊都是 1 構成,那麼正方形的面積即可作爲答案之一
這裏是以左上角爲起點
class Solution {
public int largest1BorderedSquare(int[][] g) {
int n = g.length, m = g[0].length, mi = Math.min(n, m), ans = 0;
for (int x = 0; x < n; x++)
for (int y = 0; y < m; y++) if (g[x][y] == 1) {
for (int k = 0; k <= mi; k++) {
int tx = x + k, ty = y + k; //右下角座標
if (tx >= n || ty >= m || g[x][ty] == 0 || g[tx][y] == 0)
break;
boolean flag = true;
for (int c = 0; c <= k && flag; c++) {
if (g[tx-c][ty] == 0 || g[tx][ty-c] == 0)
flag = false;
}
if (flag)
ans = Math.max(ans, k+1); //優化:(k+1)*(k+1)
}
}
return ans * ans;
}
}
小優化:可以將內部計算面積的代碼提到外面,減少乘法運算次數
複雜度分析
- 時間複雜度:,
- 空間複雜度:,
方法二:dp
這題的 dp 沒想到怎麼列方程以及如何去轉移方程,額, 還是挺難想到的…
- 定義狀態:
- 表示以 爲右下角且往左數連續 1 的個數
- 表示以 爲右下角且往上數連續 1 的個數
- 思考初始化:
- 思考狀態轉移方程:
- 如果存在 ,則有
- 如果存在 ,則有
- 我們上面只是檢查了點 的左方和上方兩個方向的連續 的個數,但我們還要檢查另外兩條邊;因爲由木桶定理得,一個矩形中的最大正方形面積由矩形 條邊的最小邊決定,所以這個檢查是必要的
class Solution {
public int largest1BorderedSquare(int[][] g) {
int n = g.length, m = g[0].length, ans = 0, f[][][] = new int[n+1][m+1][2];
for (int x = 1; x <= n; x++)
for (int y = 1; y <= m; y++) if (g[x-1][y-1] == 1) {
f[x][y][0] = f[x][y-1][0] + 1;
f[x][y][1] = f[x-1][y][1] + 1;
int k = Math.min(f[x][y-1][0], f[x-1][y][1]);
while (k > 0) {
if (f[x-k][y][0] > k && f[x][y-k][1] > k) // 長度k可以組成
break;
k--;
}
ans = Math.max(ans, k+1);
}
return ans * ans;
}
}
複雜度分析
- 時間複雜度:,
- 空間複雜度:,