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;
}
};