[leetcode]529. 扫雷游戏 DFS递归、BFS、DFS栈实现

12 篇文章 0 订阅
9 篇文章 0 订阅

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述https://leetcode-cn.com/problems/minesweeper/


DFS步骤:

1、给的x,y坐标位置是地雷board[x][y] == 'M',把那个位置标记为地雷·board[x][y] = ‘X’,返回。
2、不是地雷board[x][y]=='E',检查下这个坐标相邻位置有没有地雷:

  • 没有,标记当前位置board[x][y]='B',8个方向递归;
  • 有,标记当前位置board[x][y]=周围地雷数,不递归(注:递归是递归步骤2)

代码:

class Solution {
    int dx[8] = { -1, -1,  0,  1,  1,  1,  0, -1};  // 上,上右,右,下右,下,下左,左,上左 (顺时针)
    int dy[8] = {  0,  1,  1,  1,  0, -1, -1, -1};
    int m, n;  //长,宽
public:
    vector<vector<char>> updateBoard(vector<vector<char>>& board, 
    									vector<int>& click)
    {//题目给的
        m = board.size();
        n = board[0].size();
        DFS(board, click[0], click[1]);
        return board;
    }
    void DFS(vector<vector<char>>& board, int x, int y)
    {
        if(x < 0 || x >= m || y < 0 || y >= n)
        {
            return ;
        }
        if(board[x][y] == 'M')
        {//只在递归第一层有可能进入
            board[x][y] = 'X';
            return ;
        }
        if(board[x][y] == 'E')
        {
            board[x][y] = 'B';
            int count = countMinesweeper(board, x, y);//计算当前节点周围地雷数
            if(count == 0)
            {//count == 0说明周围是安全的,下一步不会有地雷
                for(int i = 0; i < 8; i++)
                {
                    DFS(board, x + dx[i], y + dy[i]);
                }
            }
            else
            {//周围有地雷就不能递归了
                board[x][y] = (char)(count + '0');
            }
        }
        
    }
    int countMinesweeper(vector<vector<char>>& board, int x, int y)
    {//计算当前节点周围地雷数
        int count = 0;
        for(int i = 0; i < 8; i++)
        {
            int nextX = x + dx[i];
            int nextY = y + dy[i];
            if(nextX < 0 || nextX >= m || nextY < 0 || nextY >= n)
            {
                continue;
            }
            if(board[nextX][nextY] == 'M')
            {
                count++;
            }
        }
        return count;
    }
};

改成BFS

class Solution {
    int dx[8] = { -1, -1,  0,  1,  1,  1,  0, -1};  // 上,上右,右,下右,下,下左,左,上左 (顺时针)
    int dy[8] = {  0,  1,  1,  1,  0, -1, -1, -1};
    int m, n;  //长,宽
    struct Node
    {
        int x;
        int y;
        Node(int _x, int _y)
        {
            x = _x;
            y = _y;
        }
    };
public:
    int countMinesweeper(vector<vector<char>>& board, int x, int y)
    {//计算当前节点周围地雷数
        int count = 0;
        for(int i = 0; i < 8; i++)
        {
            int nextX = x + dx[i];
            int nextY = y + dy[i];
            if(nextX < 0 || nextX >= m || nextY < 0 || nextY >= n)
            {
                continue;
            }
            if(board[nextX][nextY] == 'M')
            {
                count++;
            }
        }
        return count;
    }
    vector<vector<char>> updateBoard(vector<vector<char>>& board, 
    										vector<int>& click) 
    {
        m = board.size();
        n = board[0].size();
        int x = click[0];
        int y = click[1];
        if(board[x][y] == 'M')
        {
            board[x][y] = 'X';
            return board;
        }
        //题目说board[x][y]是'M'或'E',所以下面是对'E'的处理
        queue<Node>q;
        q.emplace(x, y);  // q.push(Node(x, y));
        while(!q.empty())
        {
            Node cur = q.front();
            q.pop();
            if(board[cur.x][cur.y] == 'E')
            {
                board[cur.x][cur.y] = 'B';
                int count = countMinesweeper(board, cur.x, cur.y);
                if(count == 0)
                {
                    for(int i = 0; i < 8; i++)
                    {
                        int nextX = cur.x + dx[i];
                        int nextY = cur.y + dy[i];
                        if(nextX < 0 || nextX >= m || nextY < 0 || nextY >= n)
                        {
                            continue;
                        }
                        q.emplace(nextX, nextY);
                    }
                }
                else
                {
                    board[cur.x][cur.y] = (char)(count + '0');
                }
            }
        }
        return board;
    }
};

在这里插入图片描述

自己用栈写DFS

看到有人自己用栈写DFS
在这里插入图片描述
改写下:
按上面的这个改的,没改对

class Solution {
    int dx[8] = { -1, -1,  0,  1,  1,  1,  0, -1};  // 上,上右,右,下右,下,下左,左,上左 (顺时针)
    int dy[8] = {  0,  1,  1,  1,  0, -1, -1, -1};
    int m, n;  //长,宽
    struct Node
    {
        int x;
        int y;
        Node(int _x, int _y)
        {
            x = _x;
            y = _y;
        }
    };
public:
    int countMinesweeper(vector<vector<char>>& board, int x, int y)
    {//计算当前节点周围地雷数
        int count = 0;
        for(int i = 0; i < 8; i++)
        {
            int nextX = x + dx[i];
            int nextY = y + dy[i];
            if(nextX < 0 || nextX >= m || nextY < 0 || nextY >= n)
            {
                continue;
            }
            if(board[nextX][nextY] == 'M')
            {
                count++;
            }
        }
        return count;
    }
    vector<vector<char>> updateBoard(vector<vector<char>>& board, vector<int>& click) {
        m = board.size();
        n = board[0].size();
        int x = click[0], y = click[1];
        if(board[x][y] == 'M')
        {
            board[x][y] = 'X';
            return board;
        }
        stack<Node>stk;
        stk.emplace(x, y);//stk.push(Node(x,y));
        board[x][y] = 'B';
        while(!stk.empty())
        {
            Node cur = stk.top();
            bool finished = true;   //标记这个分支有没有走完
            cout<<cur.x<<" "<<cur.y<<endl;
            for(int i = 0; i < 8; i++)
            {
                int nextX = cur.x + dx[i];
                int nextY = cur.y + dy[i];
                if(nextX < 0 || nextX >= m || nextY < 0 || nextY >= n)
                {
                    continue;
                }
                if(board[nextX][nextY] == 'E')
                {
                    cout<<nextX<<" ---"<<nextY<<endl;
                    int count = countMinesweeper(board, nextY, nextY);
                    if(count == 0)
                    {
                        board[nextX][nextY] = 'B';
                        finished = false;
                        stk.emplace(nextX, nextY);
                        break;
                    }
                    else
                    {
                        board[nextX][nextY] = (char)(count + '0');
                    }
                }
                
            }
            if(finished == true)
            {
                stk.pop();
            }
        }
        return board;
    }
};

我把他代码贴下,好惨,改好久也没改对
执行用时为 44 ms 的范例

void DfsStack(const int row, const int col, vector<vector<char>>& board)
    {
        static const vector<pair<int,int>> indexOffset = {{-1, 0}, {-1, 1}, {0, 1}, {1, 1}, {1, 0}, {1, -1}, {0, -1}, {-1, -1}};
        std::stack<pair<int,int>> stk;
        stk.push(pair<int,int>(row,col));
        while (!stk.empty()) {
            auto &top  = stk.top();
            bool pushed = false;
            for (const auto &e : indexOffset) {
                int i = top.first + e.first;
                int j = top.second + e.second;
                if ((i < 0) || (i >= board.size())) {
                    continue;
                }
                if ((j < 0) || (j >= board[0].size())) {
                    continue;
                }
                if (board[i][j] == 'E') {
                    int bombNum = GetBombNum(i, j, board);
                    if (bombNum > 0) {
                        board[i][j] = '0' + bombNum;
                    } else {
                        board[i][j] = 'B';
                        stk.push(pair<int,int>(i,j));
                        pushed = true;
                        break;
                    }
                }
            }
            if (pushed == false) {
                stk.pop();
            }
        }
    }
     vector<vector<char>> updateBoard(vector<vector<char>>& board, vector<int>& click) {
     if (click.size() < 2) {
         return board;
     }

     int row = click[0];
     int col = click[1];
     if (board[row][col] == 'M') {
         board[row][col] = 'X';
         return board;
     }

     if (board[row][col] == 'E') {
         int bombNum = GetBombNum(row, col, board);
         if (bombNum > 0) {
             board[row][col] = '0' + bombNum;
         } else {
             board[row][col] = 'B';
             //DfsRecursion(row, col, board);
             //std::cout << "DfsRecursion" << std::endl;

             DfsStack(row, col, board);
             std::cout << "DfsStack" << std::endl;

             //BfsQueue(row, col, board);
             //std::cout << "BfsQueue" << std::endl;
             return board;
         }
     }

     return board;
 }


按自己的思路来就没问题了

class Solution {
    int dx[8] = { -1, -1,  0,  1,  1,  1,  0, -1};  // 上,上右,右,下右,下,下左,左,上左 (顺时针)
    int dy[8] = {  0,  1,  1,  1,  0, -1, -1, -1};
    int m, n;  //长,宽
    struct Node
    {
        int x;
        int y;
        Node(int _x, int _y)
        {
            x = _x;
            y = _y;
        }
    };
public:
    int countMinesweeper(vector<vector<char>>& board, int x, int y)
    {//计算当前节点周围地雷数
        int count = 0;
        for(int i = 0; i < 8; i++)
        {
            int nextX = x + dx[i];
            int nextY = y + dy[i];
            if(nextX < 0 || nextX >= m || nextY < 0 || nextY >= n)
            {
                continue;
            }
            if(board[nextX][nextY] == 'M')
            {
                count++;
            }
        }
        return count;
    }
    vector<vector<char>> updateBoard(vector<vector<char>>& board, vector<int>& click) {
        m = board.size();
        n = board[0].size();
        int x = click[0], y = click[1];
        if(board[x][y] == 'M')
        {
            board[x][y] = 'X';
            return board;
        }
        stack<Node>stk;
        stk.emplace(x, y);//stk.push(Node(x,y));
        while(!stk.empty())
        {
            Node cur = stk.top();
            bool finished = true;   //标记这个分支有没有走完

            if(board[cur.x][cur.y] == 'E')
            {
                board[cur.x][cur.y] = 'B';
                int count = countMinesweeper(board, cur.x, cur.y);
                if(count == 0)
                {
                    for(int i = 0; i < 8; i++)
                    {
                        int nextX = cur.x + dx[i];
                        int nextY = cur.y + dy[i];
                        if(nextX < 0 || nextX >= m || nextY < 0 || nextY >= n)
                        {
                            continue;
                        }
                        stk.emplace(nextX, nextY);
                        finished = false;
                    }
                }
                else
                {
                    board[cur.x][cur.y] = (char)(count + '0');
                }
            }
            if(finished == true)
            {
                stk.pop();
            }
        }
        return board;
    }
};

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值