华为OD面试手撕真题-岛屿数量[超高频](C++ | Java | Python3 | Js | Go)实现

题目来源:力扣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

提示:

  • m == grid.length
  • n == grid[i].length
  • 1 <= m, n <= 300
  • grid[i][j] 的值为 '0' 或 '1'

思路:将二维网格看成一个无向图,竖直或水平相邻的 1 之间有边相连。为了求出岛屿的数量,我们可以扫描整个二维网格。如果一个位置为 1,则以其为起始节点开始进行深度优先搜索。在深度优先搜索的过程中,每个搜索到的 1 都会被重新标记为 0。最终岛屿的数量就是进行深度优先搜索的次数。

解析:

  1. DFS 函数 dfs

    • 参数:grid 代表二维网格,i 和 j 代表当前网格位置的行列索引。
    • 检查当前索引是否超出边界:如果 i 或 j 小于 0,或者大于等于网格的大小,则直接返回。
    • 检查当前位置是否为水('0'):如果是,则直接返回。
    • 将当前位置标记为已访问(变为 '0')。
    • 递归调用 dfs 函数,分别访问上下左右四个相邻的位置。
  2. 计算岛屿的数量函数 numIslands

    • 参数:grid 代表二维网格。
    • 初始化岛屿计数器 c 为 0。
    • 使用双层循环遍历网格的每个位置。
    • 如果找到一个新的土地('1'),调用 dfs 函数进行标记,并将岛屿计数器 c 加 1。
    • 返回岛屿的总数 c
  3. 主函数 main

    • 声明并初始化两个示例网格 grid1 和 grid2
    • 分别调用 numIslands 函数计算两个网格中的岛屿数量,并输出结果。

C++

#include<bits/stdc++.h>
using namespace std;

// 深度优先搜索 (DFS) 算法
void dfs(vector<vector<char>>& grid, int i, int j) {
    // 如果索引超出网格范围,则返回
    if (i < 0 || j < 0) {
        return;
    }
    if (i >= grid.size() || j >= grid[0].size()) {
        return;
    }

    // 如果当前位置是水 ('0'),则返回
    if (grid[i][j] == '0') {
        return;
    }

    // 将当前土地标记为已访问过(变为 '0')
    grid[i][j] = '0';

    // 递归地访问四个方向的相邻土地
    dfs(grid, i + 1, j); // 向下
    dfs(grid, i, j + 1); // 向右
    dfs(grid, i - 1, j); // 向上
    dfs(grid, i, j - 1); // 向左
}

// 计算岛屿的数量
int numIslands(vector<vector<char>>& grid) {
    int c = 0; // 岛屿计数器
    // 遍历网格中的每个元素
    for (int i = 0; i < grid.size(); i++) {
        for (int j = 0; j < grid[0].size(); j++) {
            // 如果找到一个新的岛屿(未访问过的土地 '1')
            if (grid[i][j] == '1') {
                dfs(grid, i, j); // 使用DFS将整个岛屿标记为已访问
                c++; // 岛屿计数 +1
            }
        }
    }
    return c; // 返回岛屿的总数
}

int main() {
    // 示例网格 1
    vector<vector<char>> grid1 = {
        {'1', '1', '1', '1', '0'},
        {'1', '1', '1', '1', '0'},
        {'1', '1', '0', '0', '0'},
        {'0', '0', '0', '0', '0'}
    };
    
    // 计算并输出网格 1 中的岛屿数量
    int res1 = numIslands(grid1);
    cout << res1 << endl;

    // 示例网格 2
    vector<vector<char>> grid2 = {
        {'1', '1', '0', '0', '0'},
        {'1', '1', '0', '0', '0'},
        {'0', '0', '1', '0', '0'},
        {'0', '0', '0', '1', '1'}
    };

    // 计算并输出网格 2 中的岛屿数量
    int res2 = numIslands(grid2);
    cout << res2 << endl;

    return 0; // 程序结束
}

Java 

import java.util.*;

public class Main {

    // 深度优先搜索 (DFS) 算法
    public static void dfs(char[][] grid, int i, int j) {
        // 如果索引超出网格范围,则返回
        if (i < 0 || j < 0 || i >= grid.length || j >= grid[0].length) {
            return;
        }

        // 如果当前位置是水 ('0'),则返回
        if (grid[i][j] == '0') {
            return;
        }

        // 将当前土地标记为已访问过(变为 '0')
        grid[i][j] = '0';

        // 递归地访问四个方向的相邻土地
        dfs(grid, i + 1, j); // 向下
        dfs(grid, i, j + 1); // 向右
        dfs(grid, i - 1, j); // 向上
        dfs(grid, i, j - 1); // 向左
    }

    // 计算岛屿的数量
    public static int numIslands(char[][] grid) {
        int c = 0; // 岛屿计数器
        // 遍历网格中的每个元素
        for (int i = 0; i < grid.length; i++) {
            for (int j = 0; j < grid[0].length; j++) {
                // 如果找到一个新的岛屿(未访问过的土地 '1')
                if (grid[i][j] == '1') {
                    dfs(grid, i, j); // 使用DFS将整个岛屿标记为已访问
                    c++; // 岛屿计数 +1
                }
            }
        }
        return c; // 返回岛屿的总数
    }

    // 主函数
    public static void main(String[] args) {
        // 示例网格 1
        char[][] grid1 = {
            {'1', '1', '1', '1', '0'},
            {'1', '1', '1', '1', '0'},
            {'1', '1', '0', '0', '0'},
            {'0', '0', '0', '0', '0'}
        };

        // 计算并输出网格 1 中的岛屿数量
        int res1 = numIslands(grid1);
        System.out.println(res1);

        // 示例网格 2
        char[][] grid2 = {
            {'1', '1', '0', '0', '0'},
            {'1', '1', '0', '0', '0'},
            {'0', '0', '1', '0', '0'},
            {'0', '0', '0', '1', '1'}
        };

        // 计算并输出网格 2 中的岛屿数量
        int res2 = numIslands(grid2);
        System.out.println(res2);
    }
}

Python3

def dfs(grid, i, j):
    """
    深度优先搜索 (DFS) 算法
    :param grid: 二维网格
    :param i: 当前行索引
    :param j: 当前列索引
    """
    # 如果索引超出网格范围,则返回
    if i < 0 or j < 0 or i >= len(grid) or j >= len(grid[0]):
        return

    # 如果当前位置是水 ('0'),则返回
    if grid[i][j] == "0":
        return

    # 将当前土地标记为已访问过(变为 '0')
    grid[i][j] = "0"

    # 递归地访问四个方向的相邻土地
    dfs(grid, i + 1, j)  # 向下
    dfs(grid, i, j + 1)  # 向右
    dfs(grid, i - 1, j)  # 向上
    dfs(grid, i, j - 1)  # 向左


def numIslands(grid):
    """
    计算岛屿的数量
    :param grid: 二维网格
    :return: 岛屿的数量
    """
    c = 0  # 岛屿计数器
    # 遍历网格中的每个元素
    for i in range(len(grid)):
        for j in range(len(grid[0])):
            # 如果找到一个新的岛屿(未访问过的土地 '1')
            if grid[i][j] == "1":
                dfs(grid, i, j)  # 使用DFS将整个岛屿标记为已访问
                c += 1  # 岛屿计数 +1
    return c  # 返回岛屿的总数


# 主函数
if __name__ == "__main__":
    # 示例网格 1
    grid1 = [
        ["1", "1", "1", "1", "0"],
        ["1", "1", "1", "1", "0"],
        ["1", "1", "0", "0", "0"],
        ["0", "0", "0", "0", "0"],
    ]

    # 计算并输出网格 1 中的岛屿数量
    res1 = numIslands(grid1)
    print(res1)

    # 示例网格 2
    grid2 = [
        ["1", "1", "0", "0", "0"],
        ["1", "1", "0", "0", "0"],
        ["0", "0", "1", "0", "0"],
        ["0", "0", "0", "1", "1"],
    ]

    # 计算并输出网格 2 中的岛屿数量
    res2 = numIslands(grid2)
    print(res2)

JsNode 

function dfs(grid, i, j) {
    // 如果索引超出网格范围,则返回
    if (i < 0 || j < 0 || i >= grid.length || j >= grid[0].length) {
        return;
    }

    // 如果当前位置是水 ('0'),则返回
    if (grid[i][j] === '0') {
        return;
    }

    // 将当前土地标记为已访问过(变为 '0')
    grid[i][j] = '0';

    // 递归地访问四个方向的相邻土地
    dfs(grid, i + 1, j); // 向下
    dfs(grid, i, j + 1); // 向右
    dfs(grid, i - 1, j); // 向上
    dfs(grid, i, j - 1); // 向左
}

function numIslands(grid) {
    let c = 0; // 岛屿计数器
    // 遍历网格中的每个元素
    for (let i = 0; i < grid.length; i++) {
        for (let j = 0; j < grid[0].length; j++) {
            // 如果找到一个新的岛屿(未访问过的土地 '1')
            if (grid[i][j] === '1') {
                dfs(grid, i, j); // 使用DFS将整个岛屿标记为已访问
                c++; // 岛屿计数 +1
            }
        }
    }
    return c; // 返回岛屿的总数
}

// 示例网格 1
let grid1 = [
    ['1', '1', '1', '1', '0'],
    ['1', '1', '1', '1', '0'],
    ['1', '1', '0', '0', '0'],
    ['0', '0', '0', '0', '0']
];

// 计算并输出网格 1 中的岛屿数量
let res1 = numIslands(grid1);
console.log(res1);

// 示例网格 2
let grid2 = [
    ['1', '1', '0', '0', '0'],
    ['1', '1', '0', '0', '0'],
    ['0', '0', '1', '0', '0'],
    ['0', '0', '0', '1', '1']
];

// 计算并输出网格 2 中的岛屿数量
let res2 = numIslands(grid2);
console.log(res2);

Go

package main

import (
	"fmt"
)

// 深度优先搜索 (DFS) 算法
func dfs(grid [][]byte, i, j int) {
	// 如果索引超出网格范围,则返回
	if i < 0 || j < 0 || i >= len(grid) || j >= len(grid[0]) {
		return
	}

	// 如果当前位置是水 ('0'),则返回
	if grid[i][j] == '0' {
		return
	}

	// 将当前土地标记为已访问过(变为 '0')
	grid[i][j] = '0'

	// 递归地访问四个方向的相邻土地
	dfs(grid, i+1, j) // 向下
	dfs(grid, i, j+1) // 向右
	dfs(grid, i-1, j) // 向上
	dfs(grid, i, j-1) // 向左
}

// 计算岛屿的数量
func numIslands(grid [][]byte) int {
	c := 0 // 岛屿计数器
	// 遍历网格中的每个元素
	for i := 0; i < len(grid); i++ {
		for j := 0; j < len(grid[0]); j++ {
			// 如果找到一个新的岛屿(未访问过的土地 '1')
			if grid[i][j] == '1' {
				dfs(grid, i, j) // 使用DFS将整个岛屿标记为已访问
				c++             // 岛屿计数 +1
			}
		}
	}
	return c // 返回岛屿的总数
}

func main() {
	// 示例网格 1
	grid1 := [][]byte{
		{'1', '1', '1', '1', '0'},
		{'1', '1', '1', '1', '0'},
		{'1', '1', '0', '0', '0'},
		{'0', '0', '0', '0', '0'},
	}

	// 计算并输出网格 1 中的岛屿数量
	res1 := numIslands(grid1)
	fmt.Println(res1)

	// 示例网格 2
	grid2 := [][]byte{
		{'1', '1', '0', '0', '0'},
		{'1', '1', '0', '0', '0'},
		{'0', '0', '1', '0', '0'},
		{'0', '0', '0', '1', '1'},
	}

	// 计算并输出网格 2 中的岛屿数量
	res2 := numIslands(grid2)
	fmt.Println(res2)
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
首先,在选择服务中心的最佳位置时,我们需要考虑各种因素,包括人口密度、交通便利性、基础设施和竞争对等。对于华为OD项目来说,我会推荐选址在人口密度相对较高的城市中心地带。这样可以确保服务中心能够覆盖到更多的用户群体,提高服务的便利性和覆盖面。 其次,交通便利性也是选择最佳位置的重要考量因素。一个位于交通枢纽地带的服务中心可以更容易地接触到周围城市的用户,减少用户的前往成本和时间。同时,也方便快速调度和配送产品,提高服务的效率和时效性。 此外,基础设施的完善也是一个重要的考虑因素。一个服务中心应该有稳定的电力、通讯和网络设施,以保证服务的持续性和稳定性。另外,周边商业设施和生活设施的配套也能吸引更多的顾客和员工,提高服务中心的吸引力和竞争力。 最后,对竞争对的考虑也至关重要。在选择服务中心的位置时,需要做好竞争对的地域分析,避免选择在竞争对的聚集地带,同时也要考虑如何在竞争对密集的区域提供更优质的服务和更吸引人的特色,以获得竞争优势。 综上所述,选择服务中心最佳位置需要全面考虑各种因素,包括人口密度、交通便利性、基础设施和竞争对,这样才能确保服务中心能够更好地为用户提供服务,同时也能提高企业的竞争力和影响力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值