文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

C++实现LeetCode之包围区域的示例分析

2023-06-20 18:04

关注

这篇文章将为大家详细讲解有关C++实现LeetCode之包围区域的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。

[LeetCode] 130. Surrounded Regions 包围区域

Given a 2D board containing 'X' and 'O'(the letter O), capture all regions surrounded by 'X'.

A region is captured by flipping all 'O's into 'X's in that surrounded region.

Example:

X X X X
X O O X
X X O X
X O X X

After running your function, the board should be:

X X X X
X X X X
X X X X
X O X X

Explanation:

Surrounded regions shouldn't be on the border, which means that any 'O' on the border of the board are not flipped to 'X'. Any 'O' that is not on the border and it is not connected to an 'O' on the border will be flipped to 'X'. Two cells are connected if they are adjacent cells connected horizontally or vertically.

这是道关于 XXOO 的题,有点像围棋,将包住的O都变成X,但不同的是边缘的O不算被包围,跟之前那道 Number of Islands 很类似,都可以用 DFS 来解。刚开始我的思路是 DFS 遍历中间的O,如果没有到达边缘,都变成X,如果到达了边缘,将之前变成X的再变回来。但是这样做非常的不方便,在网上看到大家普遍的做法是扫矩阵的四条边,如果有O,则用 DFS 遍历,将所有连着的O都变成另一个字符,比如 \$,这样剩下的O都是被包围的,然后将这些O变成X,把$变回O就行了。代码如下:

解法一:

class Solution {public:    void solve(vector<vector<char> >& board) {        for (int i = 0; i < board.size(); ++i) {            for (int j = 0; j < board[i].size(); ++j) {                if ((i == 0 || i == board.size() - 1 || j == 0 || j == board[i].size() - 1) && board[i][j] == 'O')                    solveDFS(board, i, j);            }        }        for (int i = 0; i < board.size(); ++i) {            for (int j = 0; j < board[i].size(); ++j) {                if (board[i][j] == 'O') board[i][j] = 'X';                if (board[i][j] == '$') board[i][j] = 'O';            }        }    }    void solveDFS(vector<vector<char> > &board, int i, int j) {        if (board[i][j] == 'O') {            board[i][j] = '$';            if (i > 0 && board[i - 1][j] == 'O')                 solveDFS(board, i - 1, j);            if (j < board[i].size() - 1 && board[i][j + 1] == 'O')                 solveDFS(board, i, j + 1);            if (i < board.size() - 1 && board[i + 1][j] == 'O')                 solveDFS(board, i + 1, j);            if (j > 0 && board[i][j - 1] == 'O')                 solveDFS(board, i, j - 1);        }    }};

很久以前,上面的代码中最后一个 if 中必须是 j > 1 而不是 j > 0,为啥 j > 0 无法通过 OJ 的最后一个大数据集合,博主开始也不知道其中奥秘,直到被另一个网友提醒在本地机子上可以通过最后一个大数据集合,于是博主也写了一个程序来验证,请参见验证 LeetCode Surrounded Regions 包围区域的DFS方法,发现 j > 0 是正确的,可以得到相同的结果。神奇的是,现在用 j > 0  也可以通过 OJ 了。

下面这种解法还是 DFS 解法,只是递归函数的写法稍有不同,但是本质上并没有太大的区别,参见代码如下:

解法二:

class Solution {public:    void solve(vector<vector<char>>& board) {        if (board.empty() || board[0].empty()) return;        int m = board.size(), n = board[0].size();        for (int i = 0; i < m; ++i) {            for (int j = 0; j < n; ++j) {                if (i == 0 || i == m - 1 || j == 0 || j == n - 1) {                    if (board[i][j] == 'O') dfs(board, i , j);                }            }           }        for (int i = 0; i < m; ++i) {            for (int j = 0; j < n; ++j) {                if (board[i][j] == 'O') board[i][j] = 'X';                if (board[i][j] == '$') board[i][j] = 'O';            }        }    }    void dfs(vector<vector<char>> &board, int x, int y) {        int m = board.size(), n = board[0].size();        vector<vector<int>> dir{{0,-1},{-1,0},{0,1},{1,0}};        board[x][y] = '$';        for (int i = 0; i < dir.size(); ++i) {            int dx = x + dir[i][0], dy = y + dir[i][1];            if (dx >= 0 && dx < m && dy > 0 && dy < n && board[dx][dy] == 'O') {                dfs(board, dx, dy);            }        }    }};

我们也可以使用迭代的解法,但是整体的思路还是一样的,在找到边界上的O后,然后利用队列 queue 进行 BFS 查找和其相连的所有O,然后都标记上美元号。最后的处理还是先把所有的O变成X,然后再把美元号变回O即可,参见代码如下:

解法三:

class Solution {public:    void solve(vector<vector<char>>& board) {        if (board.empty() || board[0].empty()) return;        int m = board.size(), n = board[0].size();        for (int i = 0; i < m; ++i) {            for (int j = 0; j < n; ++j) {                if (i != 0 && i != m - 1 && j != 0 && j != n - 1) continue;                if (board[i][j] != 'O') continue;                board[i][j] = '$';                queue<int> q{{i * n + j}};                while (!q.empty()) {                    int t = q.front(), x = t / n, y = t % n; q.pop();                    if (x >= 1 && board[x - 1][y] == 'O') {board[x - 1][y] = '$'; q.push(t - n);}                    if (x < m - 1 && board[x + 1][y] == 'O') {board[x + 1][y] = '$'; q.push(t + n);}                    if (y >= 1 && board[x][y - 1] == 'O') {board[x][y - 1] = '$'; q.push(t - 1);}                    if (y < n - 1 && board[x][y + 1] == 'O') {board[x][y + 1] = '$'; q.push(t + 1);}                }            }        }        for (int i = 0; i < m; ++i) {            for (int j = 0; j < n; ++j) {                if (board[i][j] == 'O') board[i][j] = 'X';                if (board[i][j] == '$') board[i][j] = 'O';            }        }    }};

关于“C++实现LeetCode之包围区域的示例分析”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     807人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     351人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     314人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     433人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     221人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯