LeetCode 419 BattleshipsInABoard DFS、BFS简单的入门
来源:互联网 发布:怎么看网络是否被劫持 编辑:程序博客网 时间:2024/06/10 01:14
419. Battleships in a Board
Given an 2D board, count how many different battleships are in it. The battleships are represented with 'X's, empty slots are represented with '.'s. You may assume the following rules:
- You receive a valid board, made of only battleships or empty slots.
- Battleships can only be placed horizontally or vertically. In other words, they can only be made of the shape 1xN (1 row, N columns) orNx1 (N rows, 1 column), where N can be of any size.
- At least one horizontal or vertical cell separates between two battleships - there are no adjacent battleships.
Example:
X..X...X...X
In the above board there are 2 battleships.
Invalid Example:
...XXXXX...X
This is not a valid board - as battleships will always have a cell separating between them.
Your algorithm should not modify the value of the board.
class Solution {
public:
int countBattleships(vector<vector<char>>& board) {
}
};
解题思路:
- 自己的解题思路
一开始,题目没有读懂。认为出现Case2的时候,应该返回0;而题目的意思是不考虑这种情况。如果,正确理解题意的话,这题是不怎么难的。但是这题却能扩展出很多知识,并且也让我学到不少新的知识。
思路:设置一个辅助数组,标记该网格有没有被访问到,访问到则为1,未访问则为0。之后,从左往右,从上往下,依次遍历网格,知道找到‘X’为止,接着依次往右再遍历或者往下遍历。因为题目的意思,只存在行或者列的连续X,不存在交叉现象。遍历下来,就可以得到答案。
- 别人的解题思路
程序2.1 对于特定的X进行累加,【cnt += board[r][c] == 'X' && (r == 0 || board[r - 1][c] != 'X') && (c == 0 || board[r][c - 1] != 'X');】也就是我上面程序开始遍历遇到的第一个X,之后周围的X都可以省略掉。这个程序的运行更快了。
之后的几个程序都是关于这类问题常用的几种方法,DFS和BFS。它们不单可以解决这道题目,还可以解决像Case这样的情况,所以用途更广。
学习收获:
- 对于vector<vector<int>>这种类型不够熟悉
包括初始化,申请空间,元素的提取。
比较不错的初始化:
- vector<vector<bool>> flag(m, vector<bool>(n, false));
- vector<vector<bool>> flag; flag.resize(m, vector<bool>(n, false));
提取元素: flag[i][j];
相关扩展阅读,见附件二。
- 对于二维数组的参数传值,以及如何new一个二维数组,暂时不做过多整理。有兴趣的,可以自己查资料。
- 学会了使用DFS跟BFS,对于一些简单的遍历可以写出程序。
DFS跟BFS思想很简单。再看着别人的程序,然后自己先码一遍,然后再默写一遍,基本上就over了。当然,在这过程中,你可能会质疑这个pop(),怎么放这里,push(),怎么不放在前面。多思考吧,练练就会了。
强烈推荐看我分享的代码,代码格式很规范,对于学习DFS,BFS很有帮助。
学习完了,可以拿迷宫问题练练手。
【PS:其实,我的内心是崩溃的,为什么我没有早点接触优质代码呢?因为太菜了吧!】
附件1:程序
1、自己的程序:
int countBattleships(vector<vector<char>> board)
{
//An initialization for e like shit!!! How terrible
vector<vector<int>> e(board.size());
for(int i = 0; i != board.size(); ++i)
{
e[i].reserve(board[0].size());
for(int j = 0; j != board[0].size(); ++j)
{
e[i].push_back(0);
}
}
int res = 0;
for(int i = 0; i != board.size(); ++i)
{
for(int j = 0; j != board[0].size(); ++j)
{
if(e[i][j] == 1)
{
continue;
}
if(board[i][j] == '.')
{
e[i][j] = 1;
}
else
{
res++;
int j1 = j;
while((j1 + 1) != board[0].size() && board[i][j1 + 1] == 'X')
{
++j1;
e[i][j1] = 1;
}
int i1 = i;
while((i1 + 1) != board.size() && board[i1 + 1][j] == 'X')
{
++i1;
e[i1][j] = 1;
}
}
}
}
return res;
}
2、别人的程序
int countBattleships(vector<vector<char>>& board)
{
if(board.empty() || board[0].empty()) { return 0; }
int m = board.size(), n = board[0].size(), cnt = 0;
for(int r = 0; r < m; r++)
for(int c = 0; c < n; c++)
cnt += board[r][c] == 'X' && (r == 0 || board[r - 1][c] != 'X') && (c == 0 || board[r][c - 1] != 'X');
return cnt;
}
DFS ( recursive algorithm)
class Solution
{
public:
int m, n;
vector<vector<bool>> flag;
int go[4][2] = { { 1, 0 }, { -1, 0 }, { 0, 1 }, { 0, -1 } };
void dfs(vector<vector<char>>& board, int i, int j)
{
if(i < 0 || i >= m || j < 0 || j >= n || board[i][j] == '.' || flag[i][j]) return;
flag[i][j] = true;
for(int d = 0; d < 4; ++d) dfs(board, i + go[d][0], j + go[d][1]);
}
int countBattleships(vector<vector<char>>& board)
{
if(board.empty()) return 0;
m = board.size(), n = board[0].size();
flag.resize(m, vector<bool>(n, false));
int result = 0;
for(int i = 0; i < m; ++i)
for(int j = 0; j < n; ++j)
if(board[i][j] == 'X' && !flag[i][j])
{
++result;
dfs(board, i, j);
}
return result;
}
};
DFS ( non-recursive algorithm) 【PS:自己参考上面的DFS,写的。因此,也放在这里。】
const int go[4][2] = { { 1, 0 }, { -1, 0 }, { 0, 1 }, { 0, -1 } };
class Solution
{
public:
int countBattleships(vector<vector<char>>& board)
{
if(board.empty())
{
return 0;
}
int m = board.size();
int n = board[0].size();
vector<vector<bool>> flag(m, vector<bool>(n, false));
int res = 0;
for(int i = 0; i < m; ++i)
{
for(int j = 0; j < n; ++j)
{
if(board[i][j] == 'X'&&!flag[i][j])
{
flag[i][j] = true;
++res;
stack<pair<int, int>> st;
st.push({ i, j });
while(!st.empty())
{
auto t = st.top();
//you can ponder why use line43(flag[ni][nj] = true;) not the below
//flag[t.first][t.second] = true;
int d = 0;
for(; d < 4; ++d)
{
int ni = t.first + go[d][0];
int nj = t.second + go[d][1];
if(ni < 0 || ni >= m || nj < 0 || nj >= n ||
board[ni][nj] == '.' || flag[ni][nj])
{
continue;
}
flag[ni][nj] = true;
st.push({ ni, nj });
break;
}
if(d == 4)
{
st.pop();
}
}//while
}//if
}//for2
}//for1
return res;
}
};
BFS
class Solution
{
public:
int go[4][2] = { { 1, 0 }, { -1, 0 }, { 0, 1 }, { 0, -1 } };
int countBattleships(vector<vector<char>>& board)
{
if(board.empty()) return 0;
int m = board.size(), n = board[0].size();
vector<vector<bool>> flag(m, vector<bool>(n, false));
int result = 0;
for(int i = 0; i < m; ++i)
{
for(int j = 0; j < n; ++j)
{
if(board[i][j] == 'X' && !flag[i][j])
{
++result;
queue<pair<int, int>> q;
q.push({ i, j });
while(!q.empty())
{
auto t = q.front(); q.pop();
flag[t.first][t.second] = true;
for(int d = 0; d < 4; ++d)
{
int ni = t.first + go[d][0], nj = t.second + go[d][1];
if(ni < 0 || ni >= m || nj < 0 || nj >= n || board[ni][nj] == '.' || flag[ni][nj]) continue;
q.push({ ni, nj });
}
}
}
}
}
return result;
}
};
附件2:扩展阅读
- vector容器assign(),capacity(),size(),swap(),get_allocator(),max_size(),reserve(),resize(). http://blog.csdn.net/qingqinglanghua/article/details/5035763
//这个是一维向量的例子,通过简单的程序,了解几个成员函数的作用。可以快速看看
- C++ vector多维数组初始化及清零.
http://blog.csdn.net/xiaxiazls/article/details/50018225
//这是作者整理别人的帖子,里面的内容还不错。涉及二维数组的初始化。【推荐看看前面以及最后的总结】
总结如下:
vector:对于vector赋值方式中,assign的速度是最快的,其次是resize以后用copy算法赋值,而最先能够想到的赋值操作符,速度却并不快,只能够排名第三,目前还不知道这是为什么,采用插入迭代器再用copy的方式是速度最慢的一种。
list:对于list赋值,赋值操作符的速度是最快的,其次是assign,然后是采用resize的copy,最后一位同样是采用插入迭代子方式的copy。
list:对于list赋值,赋值操作符的速度是最快的,其次是assign,然后是采用resize的copy,最后一位同样是采用插入迭代子方式的copy。
0 0
- LeetCode 419 BattleshipsInABoard DFS、BFS简单的入门
- poj3083 非常好 的入门级dfs+bfs
- DFS和BFS的一点简单总结
- bfs与dfs的最简单区别
- LeetCode:DFS,BFS
- DFS&BFS入门
- BFS和DFS入门
- POJ2386-简单BFS/DFS
- [Leetcode] bfs and dfs notes
- leetcode -- Remove Invalid Parentheses--又是DFS,BFS的题目
- 算法总结(7)--leetcode上的递归,BFS,DFS思考
- POJ 1979 简单dfs||bfs
- BFS与DFS的简单应用(一)
- BFS与DFS的简单应用(二)
- BFS与DFS的简单应用(三)
- 图的dfs、bfs
- poj1562 Oil Deposits 简单搜索,dfs和bfs都行,我用的bfs
- Clone Graph [leetcode] dfs和bfs
- 华为官方固件UPDATE.APP解包 编辑 打包详细教程
- TokuDB 引擎安装测试
- JavaScript 模块化编程 - Module Pattern
- 懒加载时为什么不能用self直接访问属性
- SQL删除重复数据只保留一条 .
- LeetCode 419 BattleshipsInABoard DFS、BFS简单的入门
- SpringMVC运行原理
- Spring bean的生命周期init和destory
- 通过样式来去除app的头以及界面全屏(备忘)
- quick-cocos UIInput字数过多崩溃问题
- json和xml传输的区别
- DHCP详解
- 【 第16周项目1-冒泡排序】
- js解决window.open 被IE弹出窗口阻止程序拦截