leetcode
leetcode 2901 ~ 2950
主题空间

主题空间

难度:

标签:

题目描述

English description is not available for the problem. Please switch to Chinese.

代码结果

运行时间: 1051 ms, 内存: 25.8 MB


/*
 * 思路:我们需要找到不与走廊('0')直接相邻的最大主题空间面积。为了实现这个功能,可以按以下步骤操作:
 * 1. 使用深度优先搜索(DFS)遍历所有的主题空间,并记录每个空间的面积。
 * 2. 在DFS过程中,如果当前主题空间与走廊相邻,标记该空间为与走廊相邻。
 * 3. 遍历所有记录的面积,找出不与走廊相邻的最大面积。
 * 使用Java Stream API改进数据处理和操作。
 */
import java.util.*;
import java.util.stream.*;

public class Solution {
    private int rows, cols;
    private boolean[][] visited;
    private char[][] grid;
    private int[] dx = {-1, 1, 0, 0};
    private int[] dy = {0, 0, -1, 1};

    public int maxArea(String[] gridStr) {
        this.rows = gridStr.length;
        this.cols = gridStr[0].length();
        this.visited = new boolean[rows][cols];
        this.grid = new char[rows][cols];

        for (int i = 0; i < rows; i++) {
            this.grid[i] = gridStr[i].toCharArray();
        }

        List<int[]> areas = new ArrayList<>();

        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                if (!visited[i][j] && grid[i][j] != '0') {
                    areas.add(dfs(i, j));
                }
            }
        }

        return areas.stream()
                .filter(result -> result[1] == 0) // 过滤不与走廊相邻的空间
                .mapToInt(result -> result[0])
                .max()
                .orElse(0);
    }

    private int[] dfs(int x, int y) {
        visited[x][y] = true;
        int area = 1;
        boolean isAdjacentToCorridor = false;

        for (int i = 0; i < 4; i++) {
            int nx = x + dx[i];
            int ny = y + dy[i];
            if (nx >= 0 && nx < rows && ny >= 0 && ny < cols) {
                if (grid[nx][ny] == '0') {
                    isAdjacentToCorridor = true;
                } else if (!visited[nx][ny] && grid[nx][ny] == grid[x][y]) {
                    int[] result = dfs(nx, ny);
                    area += result[0];
                    isAdjacentToCorridor = isAdjacentToCorridor || result[1];
                }
            }
        }

        return new int[]{area, isAdjacentToCorridor ? 1 : 0};
    }
}

解释

方法:

此题解采用了广度优先搜索(BFS)的方法来解决问题。首先,使用一个二维数组info来记录是否访问过每个单元格。初始时,将所有边界单元格以及所有的'0'(走廊)加入到搜索队列opts中,因为它们都与边界接壳。接下来,进行广度优先搜索,将与走廊相连的主题空间的每个部分标记为已访问。这一步确保了所有与走廊相连的区域都被标记。之后,再遍历数组,对于每一个未被访问的非走廊格子,从该位置出发进行广度优先搜索计算该区域的大小,并更新最大面积。最终返回最大的非与走廊相邻的主题空间面积。

时间复杂度:

O(m*n)

空间复杂度:

O(m*n)

代码细节讲解

🦆
在广度优先搜索中,如何确保所有与走廊相连的区域都被正确地标记为已访问?
在广度优先搜索(BFS)中,通过从所有边界单元格以及所有'0'(走廊)单元格开始初始化队列,并标记这些单元格为已访问,确保了搜索的起点覆盖了所有可能与外界直接接触的区域。随后,在BFS过程中,对于队列中的每个单元格,检查其四周的邻接单元格。如果邻接单元格是同类型(即走廊或相同标识的其他单元格)且未被访问过,则将其加入队列并标记为已访问。这个过程递归地标记所有与初始走廊相连的区域。因此,通过逐层扩展这种标记,可以确保所有与走廊相连的区域都被正确地标记为已访问。
🦆
为什么在初始化队列时,只将边界单元格以及'0'(走廊)单元格加入队列?非边界的'0'单元格是否也应该被加入?
在初始化队列时,将所有边界单元格以及边界上的'0'(走廊)单元格加入队列是为了从所有可能与外部直接接触的点开始广度优先搜索。这样做是因为只有这些单元格可能直接或间接与外界接壳,其他非边界的'0'单元格虽然也是走廊,但它们在初始阶段被环绕在内部,不会直接接触到边界。通过从边界开始的BFS过程自然会访问到所有与这些边界走廊相连的内部走廊,因此无需在初始阶段将它们加入队列。这样做可以减少初始队列的大小,提高效率。
🦆
在第一次执行BFS时,为什么可以保证所有与走廊相连的区域都被访问,即使走廊可能由多个不连续的部分组成?
虽然走廊可能由多个不连续的部分组成,但通过从所有边界单元格和边界上的'0'(走廊)单元格开始BFS,可以确保这些不连续部分都能被访问。这是因为BFS算法从多个起点(边界单元格和走廊)开始,能够向内部扩展,逐步访问所有与这些起点相连的区域,包括那些内部但与边界走廊直接或间接相连的走廊部分。每当访问一个走廊单元格,就会检查其四周的单元格,如果邻接单元格也是走廊且未被访问,则会被加入到BFS的下一轮迭代中,这样逐步扩展可以覆盖所有连续或不连续的走廊部分。

相关问题