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

来源:互联网 发布:mac php开发环境 编辑:程序博客网 时间:2024/06/06 11:41

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

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

  • Number of Islands
    • 题目大意
    • 思路
    • 代码
    • 关联的旧题
    • 遇到的问题
  • 200升级版695 Max Area of Island
    • 题目大意
    • 思路
    • 代码
    • 遇到的问题

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 51int 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清零。
原创粉丝点击