面试题 16.19. 水域大小

你有一个用于表示一片土地的整数矩阵land,该矩阵中每个点的值代表对应地点的海拔高度。若值为0则表示水域。由垂直、水平或对角连接的水域为池塘。池塘的大小是指相连接的水域的个数。编写一个方法来计算矩阵中所有池塘的大小,返回值需要从小到大排序。

示例:

输入:
[
  [0,2,1,0],
  [0,1,0,1],
  [1,1,0,1],
  [0,1,0,1]
]
输出: [1,2,4]

提示:

  • 0 < len(land) <= 1000
  • 0 < len(land[i]) <= 1000

在这篇博客中,我们将讨论 LeetCode 上的面试题 16.19 水域大小。我们将介绍问题的背景,给出问题的详细描述,并提供两种解决方案,分别使用 C++ 和 Java 编程语言实现。最后,我们会对解决方案进行详细的解释,并给出完整的代码。

问题背景

给定一个整数矩阵 land,其中每个点的值代表对应地点的海拔高度。矩阵中的值为 0 表示水域,而由垂直、水平或对角连接的水域构成了池塘。池塘的大小表示相连接的水域的个数。我们需要编写一个方法来计算矩阵中所有池塘的大小,并按从小到大的顺序返回结果。

问题描述

我们需要实现一个函数 pondSizes,接收一个整数矩阵 land,并返回一个整数数组,其中按从小到大的顺序存储了所有池塘的大小。

函数签名如下:

vector<int> pondSizes(vector<vector<int>>& land);
public int[] pondSizes(int[][] land);

博客:面试题 16.19 水域大小 - 寻找池塘并排序

在这篇博客中,我们将讨论 LeetCode 上的面试题 16.19 水域大小。我们将介绍问题的背景,给出问题的详细描述,并提供两种解决方案,分别使用 C++ 和 Java 编程语言实现。最后,我们会对解决方案进行详细的解释,并给出完整的代码。

问题背景

给定一个整数矩阵 land,其中每个点的值代表对应地点的海拔高度。矩阵中的值为 0 表示水域,而由垂直、水平或对角连接的水域构成了池塘。池塘的大小表示相连接的水域的个数。我们需要编写一个方法来计算矩阵中所有池塘的大小,并按从小到大的顺序返回结果。

问题描述

我们需要实现一个函数 pondSizes,接收一个整数矩阵 land,并返回一个整数数组,其中按从小到大的顺序存储了所有池塘的大小。

函数签名如下:

 
 

cppCopy code

vector<int> pondSizes(vector<vector<int>>& land);

 
 

javaCopy code

public int[] pondSizes(int[][] land);

解决方案

我们将提供两种解决方案,分别使用深度优先搜索(DFS)和广度优先搜索(BFS)。

解法一:深度优先搜索(DFS)

在这种解决方案中,我们将使用递归的深度优先搜索来找到每个池塘的大小。我们遍历整个矩阵,对于每个为 0 的点(水域),我们调用 dfs 函数来计算该点所在池塘的大小。在 dfs 函数中,我们首先检查当前点是否越界或者不是水域(即非 0 值)。如果是,我们返回 0。否则,我们将当前点的值设为 -1,以标记该点已经被访问过。然后,我们递归地调用 dfs 函数来遍历当前点的相邻点,计算池塘的大小。最后,我们返回计算得到的池塘大小。

具体的 C++ 代码如下:

class Solution {
public:
    vector<int> pondSizes(vector<vector<int>>& land) {
        int m = land.size();
        int n = land[0].size();
        vector<int> res;
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (land[i][j] == 0) {
                    res.push_back(dfs(land, i, j));
                }
            }
        }
        sort(res.begin(), res.end());
        return res;
    }

    int dfs(vector<vector<int>>& land, int x, int y) {
        int m = land.size();
        int n = land[0].size();
        if (x < 0 || x >= m || y < 0 || y >= n || land[x][y] != 0) {
            return 0;
        }
        land[x][y] = -1;
        int res = 1;
        for (int dx = -1; dx <= 1; dx++) {
            for (int dy = -1; dy <= 1; dy++) {
                if (dx == 0 && dy == 0) {
                    continue;
                }
                res += dfs(land, dx + x, dy + y);
            }
        }
        return res;
    }
};

具体的 Java 代码如下:

class Solution {
    public int[] pondSizes(int[][] land) {
        int m = land.length;
        int n = land[0].length;
        List<Integer> resList = new ArrayList<>();
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (land[i][j] == 0) {
                    resList.add(dfs(land, i, j));
                }
            }
        }
        int[] res = new int[resList.size()];
        for (int i = 0; i < resList.size(); i++) {
            res[i] = resList.get(i);
        }
        Arrays.sort(res);
        return res;
    }

    public int dfs(int[][] land, int x, int y) {
        int m = land.length;
        int n = land[0].length;
        if (x < 0 || x >= m || y < 0 || y >= n || land[x][y] != 0) {
            return 0;
        }
        land[x][y] = -1;
        int res = 1;
        for (int dx = -1; dx <= 1; dx++) {
            for (int dy = -1; dy <= 1; dy++) {
                if (dx == 0 && dy == 0) {
                    continue;
                }
                res += dfs(land, dx + x, dy + y);
            }
        }
        return res;
    }
}

解法二:广度优先搜索(BFS)

在这种解决方案中,我们将使用广度优先搜索来找到每个池塘的大小。我们遍历整个矩阵,对于每个为 0 的点(水域),我们调用 bfs 函数来计算该点所在池塘的大小。在 bfs 函数中,我们使用一个队列来存储待访问的水域点。开始时,我们将当前点加入队列,并将其值设为 -1,以标记该点已经被访问过。然后,我们进入循环,不断从队列中取出点,计算池塘的大小。对于每个取出的点,我们遍历其相邻的点,将所有为 0 的相邻点加入队列,并将其值设为 -1。最后,我们返回计算得到的池塘大小。

具体的 Java 代码如下:

class Solution {
    public int[] pondSizes(int[][] land) {
        int m = land.length;
        int n = land[0].length;
        List<Integer> resList = new ArrayList<>();
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (land[i][j] == 0) {
                    resList.add(bfs(land, i, j));
                }
            }
        }
        int[] res = new int[resList.size()];
        for (int i = 0; i < resList.size(); i++) {
            res[i] = resList.get(i);
        }
        Arrays.sort(res);
        return res;
    }

    public int bfs(int[][] land, int x, int y) {
        int m = land.length;
        int n = land[0].length;
        int res = 0;
        Queue<int[]> queue = new ArrayDeque<int[]>();
        queue.add(new int[]{x, y});
        land[x][y] = -1;
        while (!queue.isEmpty()) {
            int[] arr = queue.poll();
            int currX = arr[0], currY = arr[1];
            res++;
            for (int dx = -1; dx <= 1; dx++) {
                for (int dy = -1; dy <= 1; dy++) {
                    if (dx == 0 && dy == 0) {
                        continue;
                    }
                    if (currX + dx < 0 || currX + dx >= m || currY + dy < 0 || currY + dy >= n || land[currX + dx][currY + dy] != 0) {
                        continue;
                    }
                    land[currX + dx][currY + dy] = -1;
                    queue.add(new int[]{currX + dx, currY + dy});
                }
            }
        }
        return res;
    }
}

总结

本篇博客我们讨论了 LeetCode 上的面试题 16.19 水域大小。我们介绍了问题的背景和详细描述,并给出了两种解决方案,分别使用深度优先搜索(DFS)和广度优先搜索(BFS)。我们给出了具体的代码实现,并对解决方案进行了详细的解释。希望这篇博客对你理解和解决这道问题有所帮助。

猜你喜欢

转载自blog.csdn.net/bigBbug/article/details/131339697