LeetCode破解之陆地和水域

112 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第24天,点击查看活动详情

题目描述

给你一个大小为 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) 的高度。如果有多种解法,请返回 任意一个 。

示例 1:

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

BFS广度优先搜索

思路分析:首先我们看到这种题目,想都不用想肯定是用搜索的,不是bfs就是dfs就是看哪一种符合情况。本题就是bfs广度优先搜索。我的实现思路如下:

  • 首先确定所有水域的位置,将其值赋位0,进行初始化。
  • 在通过数组ans来构建访问矩阵,用于避免重复访问,初始水域的位置标记为已访问,防止超时。
  • 再构建结果数组,用于存放最后的结果
  • 构建一个队列queue来进行BFS搜索,进行入队出队的操作。直到队列为空停止搜索。
class Solution {
    int[][] dirs = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};

    public int[][] highestPeak(int[][] isWater) {
        int m = isWater.length, n = isWater[0].length;

        int [][] ans = new int[m][n];

        for (int i = 0 ; i < m ; i++){
            Arrays.fill(ans[i],-1);
        }

        Queue<int []> queue = new ArrayDeque<>();
        for (int i = 0 ; i < m ; i++){
            for (int j = 0 ; j < n ;j++){
                 if (isWater[i][j] == 1){
                     ans[i][j] = 0;
                     queue.offer(new int[]{i,j});
                 }
            }
        }
        while ( !queue.isEmpty() ){
            int[]p = queue.poll();
            for (int [] dir:dirs){
                int x = p[0]+dir[0],y = p[1]+dir[1];
                if (x >= 0 && x < m && y >= 0 &&y < n && ans[x][y] == -1 ){
                    ans[x][y] = ans[p[0]][p[1]]+1;
                    queue.offer(new int[]{x,y});
                }
            }
        }

        return ans;

    }
}

最后

这道题目写完才发现,是多源BFS,还去学了多源BFS,源点全部入队然后病毒式扩散至整张图结束扩散。注意的是,在用队列时,shift会超时,建议多用一个队列来辅助操作。