764. 最大加号标志

68 阅读1分钟

题目:
在一个 n x n 的矩阵 grid 中,除了在数组 mines 中给出的元素为 0,其他每个元素都为 1mines[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
}