一起刷力扣之【1765. 地图中的最高点】

193 阅读2分钟

这是我参与2022首次更文挑战的第18天,活动详情查看:2022首次更文挑战

题目

给你一个大小为 m x n 的整数矩阵 isWater ,它代表了一个由 陆地 和 水域 单元格组成的地图。

如果 isWater[i][j] == 0 ,格子 (i, j) 是一个 陆地 格子。 如果 isWater[i][j] == 1 ,格子 (i, j) 是一个 水域 格子。 你需要按照如下规则给每个单元格安排高度:

每个格子的高度都必须是非负的。 如果一个格子是是 水域 ,那么它的高度必须为 0 。 任意相邻的格子高度差 至多 为 1 。当两个格子在正东、南、西、北方向上相互紧挨着,就称它们为相邻的格子。(也就是说它们有一条公共边) 找到一种安排高度的方案,使得矩阵中的最高高度值 最大 。

请你返回一个大小为 m x n 的整数矩阵 height ,其中 height[i][j] 是格子 (i, j) 的高度。如果有多种解法,请返回 任意一个 。

示例

image.png

输入:isWater = [[0,1],[0,0]]
输出:[[1,0],[2,1]]
解释:上图展示了给各个格子安排的高度。
蓝色格子是水域格,绿色格子是陆地格。

image.png

输入:isWater = [[0,0,1],[1,0,0],[0,0,0]]
输出:[[1,1,0],[0,1,1],[1,2,2]]
解释:所有安排方案中,最高可行高度为 2 。
任意安排方案中,只要最高高度为 2 且符合上述规则的,都为可行方案。

提示

  • m == isWater.length
  • n == isWater[i].length
  • 1 <= m, n <= 1000
  • isWater[i][j] 要么是 0 ,要么是 1 。
  • 至少有 1 个水域格子。

解题思路

定义一个结果数组,先根据陆地或者水域做一个初始化的填充。

然后,我们从左上到右下,先遍历一遍,计算出一个左侧的最小值。再从右下到左上,计算出右侧的最小值,取两者间的最小值才能得出全局最小值。

例如:[1,0,0,0,0,1],左侧计算结果为[0,1,2,3,4,0],右侧计算结果为[0,4,3,2,1,0]。单次遍历的最大高度均为4,这个结果肯定是错误的,两边结合后可得[0,1,2,2,1,0]

代码实现

class Solution {
    public int[][] highestPeak(int[][] isWater) {
        int m = isWater.length, n = isWater[0].length;
        
        int[][] land = new int[m][n];
        for(int i = 0; i < m; ++i){
            for(int j = 0; j < n; ++j){
                if(isWater[i][j] == 1){
                    // 是水域,高度为 1
                    land[i][j] = 0;
                }else{
                    // 陆地,初始化为边界
                    land[i][j] = 1000 * 1000;
                }
            }
        }
        
        // 左侧遍历
        for(int i = 0; i < m; ++i){
            for(int j = 0; j < n; ++j){
                if(isWater[i][j] == 0){
                    int height = land[i][j];
                    if(i > 0){
                        height = Math.min(land[i - 1][j] + 1, height);
                    }
                    if(j > 0){
                        height = Math.min(land[i][j - 1] + 1, height);
                    }
                    land[i][j] = height;
                }
            }
        }

        // 右侧遍历
        for(int i = m - 1; i >= 0; --i){
            for(int j = n - 1; j >= 0; --j){
                if(isWater[i][j] == 0){
                    int height = land[i][j];
                    if(i < m - 1){
                        height = Math.min(land[i + 1][j] + 1, height);
                    }
                    if(j < n - 1){
                        height = Math.min(land[i][j + 1] + 1, height);
                    }
                    land[i][j] = height;
                }
            }
        }

        return land;
    }
}