云计算百科
云计算领域专业知识百科平台

Kimi LeetCode 130. 被围绕的区域 Java实现

130. 被围绕的区域

思路:直接从边界内侧做DFS会陷入"如何知道是否被包围"的困境。换个角度——所有与边界相连的 ‘O’ 都不可能被包围。所以:

  • 从四条边界的 ‘O’ 出发做 DFS/BFS,标记所有连通的 ‘O’ 为特殊标记(如 '#')
  • 遍历整个矩阵,把剩余的 'O' 改成 'X'(这些是真正被围绕的)
  • 把 '#' 还原成 'O'
  • DFS 实现

    class Solution {
    private int m, n;

    public void solve(char[][] board) {
    if (board == null || board.length == 0) return;
    m = board.length;
    n = board[0].length;

    // 从上下两条边界的 'O' 出发
    for (int j = 0; j < n; j++) {
    if (board[0][j] == 'O') dfs(board, 0, j);
    if (board[m 1][j] == 'O') dfs(board, m 1, j);
    }
    // 从左右两条边界的 'O' 出发
    for (int i = 0; i < m; i++) {
    if (board[i][0] == 'O') dfs(board, i, 0);
    if (board[i][n 1] == 'O') dfs(board, i, n 1);
    }

    // 还原 + 填充
    for (int i = 0; i < m; i++) {
    for (int j = 0; j < n; j++) {
    if (board[i][j] == 'O') board[i][j] = 'X'; // 被围绕
    else if (board[i][j] == '#') board[i][j] = 'O'; // 边界连通,保留
    }
    }
    }

    private void dfs(char[][] board, int i, int j) {
    if (i < 0 || i >= m || j < 0 || j >= n || board[i][j] != 'O') return;
    board[i][j] = '#';
    dfs(board, i + 1, j);
    dfs(board, i 1, j);
    dfs(board, i, j + 1);
    dfs(board, i, j 1);
    }
    }

    复杂度:时间 O(m \\times n),每个格子最多访问一次;空间 O(m \\times n),递归栈最坏情况。

    BFS 实现(避免递归栈溢出,适合超大矩阵)

    import java.util.ArrayDeque;
    import java.util.Deque;

    class Solution {
    public void solve(char[][] board) {
    if (board == null || board.length == 0) return;
    int m = board.length, n = board[0].length;
    Deque<int[]> queue = new ArrayDeque<>();
    int[][] dirs = {{1,0},{1,0},{0,1},{0,1}};

    // 把所有边界上的 'O' 入队
    for (int i = 0; i < m; i++) {
    if (board[i][0] == 'O') { board[i][0] = '#'; queue.offer(new int[]{i, 0}); }
    if (board[i][n1] == 'O') { board[i][n1] = '#'; queue.offer(new int[]{i, n1}); }
    }
    for (int j = 0; j < n; j++) {
    if (board[0][j] == 'O') { board[0][j] = '#'; queue.offer(new int[]{0, j}); }
    if (board[m1][j] == 'O') { board[m1][j] = '#'; queue.offer(new int[]{m1, j}); }
    }

    // BFS 标记所有与边界连通的 'O'
    while (!queue.isEmpty()) {
    int[] cur = queue.poll();
    for (int[] d : dirs) {
    int x = cur[0] + d[0], y = cur[1] + d[1];
    if (x >= 0 && x < m && y >= 0 && y < n && board[x][y] == 'O') {
    board[x][y] = '#';
    queue.offer(new int[]{x, y});
    }
    }
    }

    // 还原 + 填充
    for (int i = 0; i < m; i++) {
    for (int j = 0; j < n; j++) {
    if (board[i][j] == 'O') board[i][j] = 'X';
    else if (board[i][j] == '#') board[i][j] = 'O';
    }
    }
    }
    }

    关键点

    • 核心转化:不判断"哪些 O 被包围",而是反过来标记"哪些 O 一定不被包围"(与边界连通),剩下的就是要填充的。
    • DFS 写法简洁但最坏情况(全是 ‘O’)递归深度可达 m \\times n,可能栈溢出,面试时可主动提出 BFS 替代。
    • 进阶方案:并查集,把所有边界 ‘O’ 和一个虚拟的"边界哨兵"节点 union,最后检查每个格子是否与哨兵连通。时间复杂度同样 O(mn),面试中作为扩展思路提及即可。
    • 在这里插入图片描述
    赞(0)
    未经允许不得转载:网硕互联帮助中心 » Kimi LeetCode 130. 被围绕的区域 Java实现
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!