200. 岛屿数量(中等)
给你一个由 '1'
(陆地)和 '0'
(水)组成的的二维网格,请你计算网格中岛屿的数量。
岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。
此外,你可以假设该网格的四条边均被水包围。
示例 1:
输入:grid = [ ["1","1","1","1","0"], ["1","1","0","1","0"], ["1","1","0","0","0"], ["0","0","0","0","0"] ] 输出:1
419. 甲板上的战舰(中等)
给你一个大小为 m x n
的矩阵 board
表示甲板,其中,每个单元格可以是一艘战舰 'X'
或者是一个空位 '.'
,返回在甲板 board
上放置的 战舰 的数量。
战舰 只能水平或者垂直放置在 board
上。换句话说,战舰只能按 1 x k
(1
行,k
列)或 k x 1
(k
行,1
列)的形状建造,其中 k
可以是任意大小。两艘战舰之间至少有一个水平或垂直的空位分隔 (即没有相邻的战舰)。
示例 1:
输入:board = [["X",".",".","X"],[".",".",".","X"],[".",".",".","X"]] 输出:2
1.深度优先遍历DFS/递归法
这种方法两道题通用。
从一个点出发,若遇到‘1’,即遇到了岛屿,然后向这个‘1’的上下左右的出发,直到遇到‘0’为止,经过的‘1’也变为‘0’,即将岛屿所有节点删除,以免之后重复搜索相同岛屿。
/**
* @param {character[][]} grid
* @return {number}
*/
var numIslands = function(grid) {
let m=grid.length
let n=grid[0].length
let res=0
function turnZoro(i,j){
if(i>=m||j>=n||i<0||j<0||grid[i][j]=="0") return
grid[i][j]="0"
turnZoro(i-1,j)
turnZoro(i,j-1)
turnZoro(i+1,j)
turnZoro(i,j+1)
}
for(let i=0;i<m;i++){
for(let j=0;j<n;j++){
if(grid[i][j]=="1"){
turnZoro(i,j)
res++
}
}
}
return res
};
2.枚举起点
针对战舰数量问题:你可以实现一次扫描算法,并只使用 O(1)
额外空间,并且不修改 board
的值来解决这个问题吗?
因为题目中给定的两艘战舰之间至少有一个水平或垂直的空位分隔,任意两个战舰之间是不相邻的,因此我们可以通过枚举每个战舰的左上顶点即可统计战舰的个数。除了第一艘,每一个战舰的左、上必定是空位。
即:
满足当前位置所在的值 :board[i][j] = board[i][j]=’X’
满足当前位置的左则为空位,即board[i][j-1] = board[i][j−1]=’.’
满足当前位置的上方为空位,即board[i-1][j] = board[i−1][j]=’.’
/**
* @param {character[][]} board
* @return {number}
*/
var countBattleships = function(board) {
const row = board.length;
const col = board[0].length;
let ans = 0;
for (let i = 0; i < row; ++i) {
for (let j = 0; j < col; ++j) {
if (board[i][j] === 'X') {
if (i > 0 && board[i - 1][j] === 'X') {
continue;
}
if (j > 0 && board[i][j - 1] === 'X') {
continue;
}
//
ans++;
}
}
}
return ans;
};