LeetCode:200. Number of Islands(查找岛屿的个数)

文章最前: 我是Octopus,这个名字来源于我的中文名--章鱼;我热爱编程、热爱算法、热爱开源。所有源码在我的个人github ;这博客是记录我学习的点点滴滴,如果您对 Python、Java、AI、算法有兴趣,可以关注我的动态,一起学习,共同进步。

相关文章:

  1. LeetCode:55. Jump Game(跳远比赛)
  2. Leetcode:300. Longest Increasing Subsequence(最大增长序列)
  3. LeetCode:560. Subarray Sum Equals K(找出数组中连续子串和等于k

文章目录:

题目描述:

深度优先搜索

        java实现方法1:

        python实现方式1:

源码github地址:


题目描述:

给定一个由 '1'(陆地)和 '0'(水)组成的的二维网格,计算岛屿的数量。一个岛被水包围,并且它是通过水平方向或垂直方向上相邻的陆地连接而成的。你可以假设网格的四个边均被水包围。

示例 1:

输入:
11110
11010
11000
00000

输出: 1

示例 2:

输入:
11000
11000
00100
00011

输出: 3

来源:力扣(LeetCode)


方法1:深度优先搜索

我们可以将二维网格看成一个无向图,竖直或水平相邻的 1 之间有边相连。

为了求出岛屿的数量,我们可以扫描整个二维网格。如果一个位置为 1,则以其为起始节点开始进行深度优先搜索,在深度优先搜索的过程中,每个搜索到的 1 都会被重新标记为 0,最终岛屿的数量就是我们进行深度优先搜索的次数。

下面的画展示了整个算法:


java实现方法:

   /**
     * 计算岛屿的个数
     *
     * @param grid 二维数组
     * @return 岛屿个数
     */
    public int numIslands(char[][] grid) {
        if (grid.length == 0 || grid[0].length == 0) {
            return 0;
        }
        int res = 0;
        int row = grid.length;
        int col = grid[0].length;
        boolean[][] visited = new boolean[row][col];
        for (int i = 0; i < row; i++) {
            for (int j = 0; j < col; j++) {
                if (grid[i][j] == '1' && !visited[i][j]) {
                    helper(grid, visited, i, j);
                    res++;
                }
            }
        }
        return res;
    }

    /**
     * 递归每个元素
     *
     * @param grid    二维数组
     * @param visited 是否访问过
     * @param x       x坐标
     * @param y       y坐标
     */
    private void helper(char[][] grid, boolean[][] visited, int x, int y) {
        if (x < 0 || x >= grid.length) {
            return;
        }
        if (y < 0 || y >= grid[0].length) {
            return;
        }
        if (grid[x][y] != '1' || visited[x][y]) {
            return;
        }
        visited[x][y] = true;
        helper(grid, visited, x - 1, y);
        helper(grid, visited, x + 1, y);
        helper(grid, visited, x, y - 1);
        helper(grid, visited, x, y + 1);
    }

时间复杂度:O(MN),其中 M 和 N分别为行数和列数。

空间复杂度:O(MN),在最坏情况下,整个网格均为陆地,深度优先搜索的深度达到 M N。


python实现方式:

from typing import List


def num_islands(grid: List[List[str]]) -> int:
    '''
         计算岛屿个数
    Args:
        grid: 二维数组
    Returns:
        岛屿个数

    '''
    if len(grid) < 1 or len(grid[0]) < 1:
        return 0
    result = 0
    row, col = len(grid), len(grid[0])
    visited = [[False] * col for x in range(row)]
    for i in range(row):
        for j in range(col):
            if grid[i][j] == '1' and not visited[i][j]:
                helper(grid, visited, i, j)
                result += 1
    return result


def helper(grid: List[List[int]], visited: List[List[int]], x: int, y: int) -> None:
    '''
        帮助类函数
    Args:
        grid: 二维数组
        visited: 访问数组
        x: 位置x
        y: 位置y
    '''
    if x < 0 or x >= len(grid):
        return
    if y < 0 or y >= len(grid[0]):
        return
    if grid[x][y] != '1' or visited[x][y]:
        return
    visited[x][y] = True
    helper(grid, visited, x - 1, y)
    helper(grid, visited, x + 1, y)
    helper(grid, visited, x, y - 1)
    helper(grid, visited, x, y + 1)

时间复杂度:O(MN),其中 M 和 N分别为行数和列数。

空间复杂度:O(MN),在最坏情况下,整个网格均为陆地,深度优先搜索的深度达到 M N。


源码github地址:

https://github.com/zhangyu345293721/leetcode

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
给定一个整数数组 nums 和一个目标值 target,要求在数组中找出两个数的和等于目标值,并返回这两个数的索引。 思路1:暴力法 最简单的思路是使用两层循环遍历数组的所有组合,判断两个数的和是否等于目标值。如果等于目标值,则返回这两个数的索引。 此方法的时间复杂度为O(n^2),空间复杂度为O(1)。 思路2:哈希表 为了优化时间复杂度,可以使用哈希表来存储数组中的元素和对应的索引。遍历数组,对于每个元素nums[i],我们可以通过计算target - nums[i]的值,查找哈希表中是否存在这个差值。 如果存在,则说明找到了两个数的和等于目标值,返回它们的索引。如果不存在,将当前元素nums[i]和它的索引存入哈希表中。 此方法的时间复杂度为O(n),空间复杂度为O(n)。 思路3:双指针 如果数组已经排序,可以使用双指针的方法来求解。假设数组从小到大排序,定义左指针left指向数组的第一个元素,右指针right指向数组的最后一个元素。 如果当前两个指针指向的数的和等于目标值,则返回它们的索引。如果和小于目标值,则将左指针右移一位,使得和增大;如果和大于目标值,则将右指针左移一位,使得和减小。 继续移动指针,直到找到两个数的和等于目标值或者左指针超过了右指针。 此方法的时间复杂度为O(nlogn),空间复杂度为O(1)。 以上三种方法都可以解决问题,选择合适的方法取决于具体的应用场景和要求。如果数组规模较小并且不需要考虑额外的空间使用,则暴力法是最简单的方法。如果数组较大或者需要优化时间复杂度,则哈希表或双指针方法更合适。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值