【算法分析与设计】【第七周】200 & 695. Number(Max Area) of Islands

题目来源:200:https://leetcode.com/problems/number-of-islands/description/
695:https://leetcode.com/problems/max-area-of-island/description/

BFS\DFS巩固。关联旧题。小题升级。

200. Number of Islands

题目大意

在字符“0”和“1”组成的矩阵中,“0”代表海水,“1”代表岛屿,连在一起的小岛屿组成一个大岛(对角线不算连在一起)。
找出大岛的总个数。


11000
11000
00100
00011
Answer: 3

思路

  • 利用一个visited二维数组来标志一个数是否被访问过。
  • 利用广度优先搜索来找连在一起的小岛屿所组成的一个大岛。
  • 统计广度优先搜索的次数,即大岛的总个数。

代码

#define NMAX 1000 
int visited[NMAX][NMAX] = {0};      
void bfs(char** grid, int gridRowSize, int gridColSize, int i, int j) {
    if (i >= 0 && i < gridRowSize && j >= 0 && j < gridColSize && !visited[i][j] && grid[i][j] == '1') {
        visited[i][j] = 1;
        bfs(grid, gridRowSize, gridColSize, i - 1, j);
        bfs(grid, gridRowSize, gridColSize, i, j - 1);
        bfs(grid, gridRowSize, gridColSize, i, j + 1);
        bfs(grid, gridRowSize, gridColSize, i + 1, j);
    }
} 

int numIslands(char** grid, int gridRowSize, int gridColSize) {
    for (int i = 0; i < NMAX; i++) 
        for (int j = 0; j < NMAX; j++) 
            visited[i][j] = 0;
    int count = 0; 
    for (int i = 0; i < gridRowSize; i++) {
        for (int j = 0; j < gridColSize; j++) {
            if (visited[i][j] == 0 && grid[i][j] == '1') {
                count++;
                bfs(grid, gridRowSize, gridColSize, i, j);
            }
        }
    }
    return count;
}

关联的旧题

200这题可以说是博客第四周记录的题目547. Friend Circles的升级版。
547也是一道与图有关的题目,可简化成找出无向图中连通图的个数。
相较之下,200与典型的图不太相同,不能简单地说有向无向,毕竟行列数都不一致。为了解决行列数不一致的问题,我们只好把visited数组从一维数组改为二维数组,用于记录grid中的每个点。难度有所提升。

遇到的问题

处理下标的时候,想到grid的边界和中间应该采用不同的递归式。比如grid[0][0]就只用找grid[0][1]、grid[1][0],并不用上下左右都找一边,找了也是越界。于是写了一下几个边界处理:

    if (i > 0 && i < gridRowSize-1 && j > 0 && j < gridColSize-1 && !visited[i][j] && grid[i][j] == '1') {
        visited[i][j] = 1;
        bfs(grid, gridRowSize, gridColSize, i - 1, j);
        bfs(grid, gridRowSize, gridColSize, i, j - 1);
        bfs(grid, gridRowSize, gridColSize, i, j + 1);
        bfs(grid, gridRowSize, gridColSize, i + 1, j);
    } else if (i == 0 && j > 0 && j < gridColSize-1 && !visited[i][j] && grid[i][j] == '1') {
        visited[i][j] = 1;
        bfs(grid, gridRowSize, gridColSize, i, j - 1);
        bfs(grid, gridRowSize, gridColSize, i, j + 1);
        bfs(grid, gridRowSize, gridColSize, i + 1, j);
    } else if (i > 0 && i < gridRowSize-1 && j == 0 && !visited[i][j] && grid[i][j] == '1') {
        visited[i][j] = 1;
        bfs(grid, gridRowSize, gridColSize, i - 1, j);
        bfs(grid, gridRowSize, gridColSize, i, j + 1);
        bfs(grid, gridRowSize, gridColSize, i + 1, j);
    } else if (i == 0 && j == 0 && grid[i][j] == '1') {
        visited[i][j] = 1;
        bfs(grid, gridRowSize, gridColSize, i, j + 1);
        bfs(grid, gridRowSize, gridColSize, i + 1, j);
    } else if (i == gridRowSize-1 && j > 0 && j < gridColSize-1 && !visited[i][j] && grid[i][j] == '1') {
        visited[i][j] = 1;
        bfs(grid, gridRowSize, gridColSize, i - 1, j);
        bfs(grid, gridRowSize, gridColSize, i, j - 1);
        bfs(grid, gridRowSize, gridColSize, i, j + 1);
    } else if (i > 0 && i < gridRowSize-1 && j == gridColSize-1 && !visited[i][j] && grid[i][j] == '1') {
        visited[i][j] = 1;
        bfs(grid, gridRowSize, gridColSize, i - 1, j);
        bfs(grid, gridRowSize, gridColSize, i, j - 1);
        bfs(grid, gridRowSize, gridColSize, i + 1, j);
    } else if (i == gridRowSize-1 && j == gridColSize-1 && !visited[i][j] && grid[i][j] == '1') {
        visited[i][j] = 1;
        bfs(grid, gridRowSize, gridColSize, i - 1, j);
        bfs(grid, gridRowSize, gridColSize, i, j - 1);
    }

但是关心则乱,一通处理下来,反而使算法的逻辑不清楚了。运行了一下,错误bug一堆。但是这么一大坨代码,自己根本都不想看。
后来静下来捋一捋,发现越界的行列参数i、j根本传不进if语句,一大坨可以直接简化成:

    if (i >= 0 && i < gridRowSize && j >= 0 && j < gridColSize && !visited[i][j] && grid[i][j] == '1') {
        visited[i][j] = 1;
        bfs(grid, gridRowSize, gridColSize, i - 1, j);
        bfs(grid, gridRowSize, gridColSize, i, j - 1);
        bfs(grid, gridRowSize, gridColSize, i, j + 1);
        bfs(grid, gridRowSize, gridColSize, i + 1, j);
    }

嗯,舒服多了。
~ o( ̄▽ ̄)o~


(200升级版)695. Max Area of Island

题目大意

在0和1组成的矩阵中,0代表海水,1代表岛屿,连在一起的小岛屿组成一个大岛(对角线不算连在一起)。
找出所有大岛中最大的岛,并输出组成该大岛的小岛屿的个数。


[[0,0,1,0,0,0,0,1,0,0,0,0,0],
[0,0,0,0,0,0,0,1,1,1,0,0,0],
[0,1,1,0,1,0,0,0,0,0,0,0,0],
[0,1,0,0,1,1,0,0,1,0,1,0,0],
[0,1,0,0,1,1,0,0,1,1,1,0,0],
[0,0,0,0,0,0,0,0,0,0,1,0,0],
[0,0,0,0,0,0,0,1,1,1,0,0,0],
[0,0,0,0,0,0,0,1,1,0,0,0,0]]
Given the above grid, return 6.

思路

这题其实和200是一模一样的,只不过多了一步“输出组成该大岛的小岛屿的个数”。这很容易解决,只要加一个计数器,在每次扫描点的时候把该连通区域内扫过的点的个数累加便可。

代码

为了方便,这里的计数器用全局变量。

#include <stdio.h>
#include <stdlib.h>
#define NMAX 51
int visited[NMAX][NMAX] = {0};      
int count = 0;
void bfs(int** grid, int gridRowSize, int gridColSize, int i, int j) {
    if (i >= 0 && i < gridRowSize && j >= 0 && j < gridColSize && !visited[i][j] && grid[i][j] == 1) {
        count++;    
        visited[i][j] = 1;
        bfs(grid, gridRowSize, gridColSize, i - 1, j);
        bfs(grid, gridRowSize, gridColSize, i, j - 1);
        bfs(grid, gridRowSize, gridColSize, i, j + 1);
        bfs(grid, gridRowSize, gridColSize, i + 1, j);
    }
} 

int maxAreaOfIsland(int** grid, int gridRowSize, int gridColSize) {  
    for (int i = 0; i < NMAX; i++) 
        for (int j = 0; j < NMAX; j++) 
            visited[i][j] = 0;
    int max = 0;
    for (int i = 0; i < gridRowSize; i++) {
        for (int j = 0; j < gridColSize; j++) {
            count = 0;
            if (visited[i][j] == 0 && grid[i][j] == 1) {
                bfs(grid, gridRowSize, gridColSize, i, j);
                if (count > max) max = count;
            }
        }
    }
    return max;
}

遇到的问题

没啥大问题

  • 不要把max和count混淆。
  • 每一次做bfs前要把count清零。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值