uacs2024

导航

leetcode130. 被围绕的区域

130. 被围绕的区域

给你一个m x n的矩阵board,由若干字符'X'和'O',找到所有被'X'围绕的区域,并将这些区域所有的'O'用'X'填充。

首先是想了很久的🤡错误解法:

class Solution {
public:
    void dfs(vector<vector<char>>& board,int i,int j,bool &isEdge){
        if(i == -1 || i == board.size() || j == -1 || j == board[0].size())  return;
        if(board[i][j] == 'X' || board[i][j] == '-' || board[i][j] == 'E')  return;
        if(board[i][j] == 'O' && (i == 0 || i == board.size()-1 || j == 0 || j == board[0].size()-1))  isEdge = true;
        board[i][j] = '-';//遍历过的网格点改为'-'
        dfs(board,i-1,j,isEdge);dfs(board,i+1,j,isEdge);
        dfs(board,i,j-1,isEdge);dfs(board,i,j+1,isEdge);
        if(isEdge == true)  board[i][j] = 'E';
    }
    void solve(vector<vector<char>>& board) {
        for(int i = 0;i < board.size();++i){
            for(int j = 0;j < board[0].size();++j){
                bool isEdge = false;
                dfs(board,i,j,isEdge);
            }
        }
        for(int i = 0;i < board.size();++i){
            for(int j = 0;j < board[0].size();++j){
                if(board[i][j] == 'E')  board[i][j] = 'O';
                else  board[i][j] = 'X';
            }
        }
    }
};

错误分析

  1. 错误的全盘遍历逻辑

    • 原代码遍历了整个矩阵的每一个单元格,对每个单元格都进行DFS判断

    • 这会导致极端低效的 O(n^4) 时间复杂度(例如当整个矩阵都是O时)

    • 正确做法应该只从边界出发进行DFS/BFS

  2. 错误的状态管理

    • 使用成员变量 isEdge 会导致递归调用间的状态污染

    • 当多个递归调用共享同一个状态变量时,会出现错误标记

正确解法

class Solution {
public:
    // 深度优先搜索函数,用于标记与边界相连的'O'
    void dfs(vector<vector<char>>& board, int i, int j) {
        // 检查是否越界
        if(i == -1 || i == board.size() || j == -1 || j == board[0].size())  
            return;
        // 如果当前字符不是'O',直接返回
        if(board[i][j] != 'O')  
            return;
        
        // 将边界相连的'O'标记为'E'(Escape的缩写,表示可以逃出)
        board[i][j] = 'E';
        
        // 向四个方向继续深度搜索
        dfs(board, i-1, j);  //
        dfs(board, i+1, j);  //
        dfs(board, i, j-1);  //
        dfs(board, i, j+1);  //
    }

    void solve(vector<vector<char>>& board) {
        // 获取矩阵的行数和列数
        int m = board.size(), n = board[0].size();
        
        // 第一步:标记所有与边界相连的'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 j = 1; j < n - 1; ++j) {
            if(board[0][j] == 'O')  // 上边界
                dfs(board, 0, j);
            if(board[m-1][j] == 'O')  // 下边界
                dfs(board, m-1, j);
        }
        
        // 第二步:遍历整个矩阵,进行最终处理
        for(int i = 0; i < m; ++i) {
            for(int j = 0; j < n; ++j) {
                if(board[i][j] == 'E')  
                    // 被标记为'E'的恢复为'O'(这些是与边界相连的)
                    board[i][j] = 'O';
                else  
                    // 其他情况(包括原来的'O'和'X')
                    // 原来的'O'现在应该被包围,改为'X'
                    // 原来的'X'保持不变
                    board[i][j] = 'X';
            }
        }
    }
};

 

posted on 2025-03-27 14:39  ᶜʸᵃⁿ  阅读(19)  评论(0)    收藏  举报