[算法练习3] - 深度优先M(岛屿数量 js)

leetcode 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
示例 2:

输入:grid = [
[“1”,“1”,“0”,“0”,“0”],
[“1”,“1”,“0”,“0”,“0”],
[“0”,“0”,“1”,“0”,“0”],
[“0”,“0”,“0”,“1”,“1”]
]
输出:3

解决方案

[算法练习3] - 深度优先M(岛屿数量 js)_第1张图片

岛屿数量计算算法(不修改原数组)

为了在不修改原数组的情况下计算岛屿的数量,我们可以使用一个辅助数组来标记访问过的陆地单元格。这个辅助数组的大小与原数组相同,并将所有值初始化为false,表示所有单元格都未被访问。在深度优先搜索过程中,我们将访问过的陆地单元格在辅助数组中对应的位置标记为true。

下面是不修改原数组计算岛屿数量的算法实现:

function numIslands(grid) {
    if (!grid || grid.length === 0 || grid[0].length === 0) {
        return 0;
    }

    let numIslands = 0;
    let rows = grid.length;
    let cols = grid[0].length;
    let visited = Array.from({length: rows}, () => Array(cols).fill(false));

    for (let r = 0; r < rows; r++) {
        for (let c = 0; c < cols; c++) {
            if (grid[r][c] === '1' && !visited[r][c]) {
                dfs(grid, r, c, visited);
                numIslands++;
            }
        }
    }

    return numIslands;
}

function dfs(grid, r, c, visited) {
    const rows = grid.length;
    const cols = grid[0].length;

    if (r < 0 || c < 0 || r >= rows || c >= cols || grid[r][c] === '0' || visited[r][c]) {
        return;
    }

    visited[r][c] = true; // Mark as visited

    // Explore the neighbors in the four directions
    dfs(grid, r - 1, c, visited); // up
    dfs(grid, r + 1, c, visited); // down
    dfs(grid, r, c - 1, visited); // left
    dfs(grid, r, c + 1, visited); // right
}

// 示例 1
const grid1 = [
    ["1","1","1","1","0"],
    ["1","1","0","1","0"],
    ["1","1","0","0","0"],
    ["0","0","0","0","0"]
];
console.log(numIslands(grid1)); // 输出:1

// 示例 2
const grid2 = [
    ["1","1","0","0","0"],
    ["1","1","0","0","0"],
    ["0","0","1","0","0"],
    ["0","0","0","1","1"]
];
console.log(numIslands(grid2)); // 输出:3

在上述代码中,我们引入了一个名为visited的二维数组,用于跟踪已经访问过的单元格。在dfs函数中,我们不仅要检查当前单元格是否是陆地,还要检查它是否已经被访问过。如果满足这两个条件,我们才会继续递归地搜索相邻的单元格。这样,我们可以在不修改原数组的情况下计算出岛屿的数量。

进一步求 leetcode 695. 岛屿的最大面积

为了计算岛屿的最大面积,我们可以在前面的基础上做一些修改。我们仍然使用一个辅助数组来标记访问过的单元格,但是在深度优先搜索过程中,我们会累加每个岛屿的面积,并更新最大面积。

下面是计算岛屿最大面积的算法实现:

function maxAreaOfIsland(gridTemp) {
	
	if (!gridTemp || gridTemp.length === 0 || gridTemp[0].length === 0) {
			return 0;
	}
	let grid = gridTemp.map(x => {
		const arr = x.map(y => {
			return y.toString()
		})
		return arr
	})

	let maxArea = 0;
	let rows = grid.length;
	let cols = grid[0].length;
	let visited = Array.from({length: rows}, () => Array(cols).fill(false));

	for (let r = 0; r < rows; r++) {
			for (let c = 0; c < cols; c++) {
					if (grid[r][c] === '1' && !visited[r][c]) {
							let area = dfs(grid, r, c, visited);
							maxArea = Math.max(maxArea, area);
					}
			}
	}

	return maxArea;
}

function dfs(grid, r, c, visited) {
	const rows = grid.length;
	const cols = grid[0].length;

	if (r < 0 || c < 0 || r >= rows || c >= cols || grid[r][c] === '0' || visited[r][c]) {
			return 0;
	}

	visited[r][c] = true; // Mark as visited
	let area = 1; // Current cell area

	// Explore the neighbors in the four directions and accumulate the area
	area += dfs(grid, r - 1, c, visited); // up
	area += dfs(grid, r + 1, c, visited); // down
	area += dfs(grid, r, c - 1, visited); // left
	area += dfs(grid, r, c + 1, visited); // right

	return area;
}

你可能感兴趣的:(算法,深度优先,javascript)