题目:
在一个 n x n 的矩阵 grid 中,除了在数组 mines 中给出的元素为 0,其他每个元素都为 1。mines[i] = [xi, yi]表示 grid[xi][yi] == 0
返回 **grid 中包含 1 的最大的 轴对齐 加号标志的阶数 。如果未找到加号标志,则返回 0 。
一个 k 阶由 1 组成的 “轴对称”加号标志 具有中心网格 grid[r][c] == 1 ,以及4个从中心向上、向下、向左、向右延伸,长度为 k-1,由 1 组成的臂。注意,只有加号标志的所有网格要求为 1 ,别的网格可能为 0 也可能为 1 。
算法:
方法一:模拟
超时
func orderOfLargestPlusSign(n int, mines [][]int) int {
ans := 0
isZero := make(map[int]bool, 0)
for i := range mines {
isZero[mines[i][0] * n + mines[i][1]] = true
}
for i := 0; i < n; i ++ {
for j := 0; j < n; j ++ {
if isZero[i * n + j] {
continue
}
d := 1
for 0 <= i - d && i + d < n && 0 <= j -d && j + d < n {
if isZero[(i - d) * n + j] || isZero[(i + d) * n + j] || isZero[i * n + j - d] || isZero[i * n + j + d] {
break
}
d ++
}
if d > ans {
ans = d
}
}
}
return ans
}
方法二:剪枝
func orderOfLargestPlusSign(n int, mines [][]int) int {
ans := 0
isZero := make(map[int]bool, 0)
for i := range mines {
isZero[mines[i][0] * n + mines[i][1]] = true
}
for i := 0; i < n; i ++ {
for j := 0; j < n; j ++ {
if isZero[i * n + j] {
continue
}
// 稍微剪枝
maxD := min(min(min(i, n - i -1), j), n - j - 1) + 1
if maxD < ans {
continue
}
d := 1
for 0 <= i - d && i + d < n && 0 <= j - d && j + d < n {
if isZero[(i - d) * n + j] || isZero[(i + d) * n + j] || isZero[i * n + j - d] || isZero[i * n + j + d] {
break
}
d ++
}
if d > ans {
ans = d
}
}
}
return ans
}
func min(a, b int) int {
if a < b {
return a
}
return b
}
方法二:预处理+模拟
预处理计算(i,j)坐标四个方向上最长的的连续1个数,取四个方向上的最小值作为加号的阶
func orderOfLargestPlusSign(n int, mines [][]int) int {
ans := 0
grid := make([][]int, n + 2)
toRight, toDown := make([][]int, n + 2), make([][]int, n + 2)
toLeft, toUp := make([][]int, n + 2), make([][]int, n + 2)
for i := range grid {
grid[i] = make([]int, n + 2)
toRight[i] = make([]int, n + 2)
toDown[i] = make([]int, n + 2)
toLeft[i] = make([]int, n + 2)
toUp[i] = make([]int, n + 2)
}
for i := 1; i <= n; i ++ {
for j := 1; j <= n; j ++ {
grid[i][j] = 1
}
}
for i := range mines {
x, y := mines[i][0] + 1, mines[i][1] + 1
grid[x][y] = 0
}
for i := 1; i <= n; i ++ {
for j := 1; j <= n; j ++ {
if grid[i][j] == 1 {
toRight[i][j] = toRight[i][j - 1] + 1
toDown[i][j] = toDown[i - 1][j] + 1
}
if grid[n - i + 1][n - j + 1] == 1 {
toUp[n - i + 1][n - j + 1] = toUp[n - i + 2][n - j + 1] + 1
toLeft[n - i + 1][n - j + 1] = toLeft[n - i + 1][n - j + 2] + 1
}
}
}
for i := 1; i <= n; i ++ {
for j := 1; j <= n; j ++ {
ans = max(min(min(min(toRight[i][j], toLeft[i][j]), toDown[i][j]), toUp[i][j]),ans)
}
}
return ans
}
func min(a, b int) int {
if a < b {
return a
}
return b
}
func max(a, b int) int {
if a > b {
return a
}
return b
}