764 Largest Plus Sign
You are given an integer n. You have an n x n binary grid grid with all values initially 1's except for some indices given in the array mines. The ith element of the array mines is defined as mines[i] = [xi, yi] where grid[xi][yi] == 0.
Return the order of the largest axis-aligned plus sign of 1's contained in grid. If there is none, return 0.
An axis-aligned plus sign of 1's of order k has some center grid[r][c] == 1 along with four arms of length k - 1 going up, down, left, and right, and made of 1's. Note that there could be 0's or 1's beyond the arms of the plus sign, only the relevant area of the plus sign is checked for 1's.
Example 1:

Input: n = 5, mines = [[4,2]]
Output: 2
Explanation: In the above grid, the largest plus sign can only be of order 2. One of them is shown.
Example 2:

Solution:
class Solution {
public int orderOfLargestPlusSign(int n, int[][] mines) {
// base case
if (n == 0){
return 0;
}
if (n == 1 && mines[0].length == 0){
return 0;
}
int[][] matrix = new int[n][n];
for (int i = 0; i < n; i++){
for (int j = 0; j < n; j++){
matrix[i][j] = 1;
}
}
for (int[] mine : mines){
matrix[mine[0]][mine[1]] = 0;
}
// leftup records the longest possible length for left and up
// arms ending at each cells in the matrix
int[][] leftUp = leftUp(matrix, n);
// rightdown records the longest possible length for right and down
// arms ending at each cells in the matrix
int[][] rightDown = rightDown(matrix, n);
// merge the two matrix by getting the min value for each cell,
// and among all the cells get the max value;
return merge(leftUp, rightDown, n);
}
// merge leftUp and rightDown matrix into leftUp,
// the value of each cell is the min value of the corresponding cells
// in the two matrix, also it returns the max value among all the cells
// in the merged matrix.
private int merge(int[][] leftUp, int[][] rightDown, int n){
int result = 0;
for (int i = 0; i < n; i++){
for (int j = 0; j < n; j++){
leftUp[i][j] = Math.min(leftUp[i][j], rightDown[i][j]);
result = Math.max(result, leftUp[i][j]);
}
}
return result;
}
// calculate the max possible length of left and up arms
// for each of the cells in the matrix.
private int[][] leftUp(int[][] matrix, int n){
int[][] left = new int[n][n];
int[][] up = new int[n][n];
for (int i = 0; i < n; i++){
for (int j = 0; j < n; j++){
if (matrix[i][j] == 1){
if (i == 0 && j == 0){// 第一行 第一列
up[i][j] = 1;
left[i][j] = 1;
} else if (i == 0){// 第一行
up[i][j] = 1;
left[i][j] = left[i][j-1] + 1;
} else if (j == 0){// 第一列
up[i][j] = up[i-1][j] + 1;
left[i][j] = 1;
} else {
up[i][j] = up[i-1][j] + 1;
left[i][j] = left[i][j - 1] + 1;
}
}
}
}
merge(left, up, n);
return left;
}
/*
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
1 1 0 1 1
left
1 2 3 4 5 1 1 1 1 1
1 2 3 4 5 1 2 2 2 2
1 2 3 4 5 -> 1 2 3 3 3
1 2 3 4 5 1 2 3 4 4
1 2 0 1 2 1 2 0 1 2
up
1 1 1 1 1
2 2 2 2 2
3 3 3 3 3
4 4 4 4 4
5 5 0 5 5
*/
// calculate the max possible length of right and down arms
// for each of the cells in the matrix
private int[][] rightDown(int[][] matrix, int n){
int[][] right = new int[n][n];
int[][] down = new int[n][n];
for (int i = n-1; i >= 0; i--){
for (int j = n-1; j>=0; j--){
if (matrix[i][j] == 1){
if (i == n - 1 && j == n-1){ // 最后一行最后一列个
down[i][j] = 1;
right[i][j] = 1;
} else if (i == n-1){ // 最后一行
down[i][j] = 1;
right[i][j] = right[i][j+1]+1;
} else if (j == n-1){
down[i][j] = down[i + 1][j] + 1;
right[i][j] = 1;
} else {
down[i][j] = down[i + 1][j] + 1;
right[i][j] = right[i][j + 1] +1;
}
}
}
}
// merge right and down, return the merge matrix
merge(right, down, n);
return right;
}
/*
right
5 4 3 2 1
5 4 3 2 1
5 4 3 2 1
5 4 3 2 1
2 1 0 2 1
down
5 5 4 5 5
4 4 3 4 4
3 3 2 3 3
2 2 1 2 2
1 1 0 1 1
merge
5 4 3 2 1
4 4 3 2 1
3 3 2 2 1
2 2 1 2 1
1 1 0 1 1
up
1 1 1 1 1
1 2 2 2 2
1 2 3 3 3
1 2 3 4 4
1 2 0 1 2
1 1 1 1 1
1 2 2 2 1
1 2 2 2 1
1 2 1 2 1
1 1 0 1 1
*/
}
// TC: O(n^2)
// SC: O(n^2)