岛问题

一个矩阵中只有0和1两种值,每个位置都可以和自己的上、下、左、右四个位置相连,如果有一片1连在一起,这个部分叫做一个岛。求一个矩阵中有多少个岛?

(注意是上下左右,斜着来不行)

这个问题有点类似于N皇后问题,我们采取的策略都是“感染”。我们遍历这个数组,一旦发现有1,那么我们就朝着其上下左右四个方向进行感染,然后递归进行这个操作。主要思路就是这样,现在我们来看看具体如何实现:

 1 public static int countIslands(int[][] arr) {
 2         if (arr == null || arr[0] == null) {
 3             return 0;
 4         }
 5         int result = 0;
 6         int row = arr.length;
 7         int col = arr[0].length;
 8         for (int i = 0; i < row; ++i) {
 9             for (int j = 0; j < col; ++j) {
10                 if (arr[i][j] == 1) {
11                     ++result;
12                     infect(arr, i, j, row, col);
13                 }
14             }
15         }
16         return result;
17     }

这个是主要方法,首先是递归结束条件,这个很简单就不多说了。然后,是核心代码。遍历这个数组,一旦发现有一个数是1,立刻感染周围。

接下来我们来看看感染的代码:

 1 private static void infect(int[][] arr, int i, int j, int row, int col) {
 2         //i是行,j是列
 3         if (i < 0 || i >= row || j < 0 || j >= col || arr[i][j] != 1) {
 4             return;
 5         }
 6         arr[i][j] = 2;
 7         infect(arr, i + 1, j, row, col);
 8         infect(arr, i - 1, j, row, col);
 9         infect(arr, i, j + 1, row, col);
10         infect(arr, i, j - 1, row, col);
11     }

感染的过程是一个递归的过程。在这里我们需要做的,首先就是判断是否是感染目标,数值为0的具有免疫功能,因此不能被感染。我们需要找到的就是数值为1的“易感染个体”。每找到一个1,我们就把它转化为2,然后让它继续感染周围为1的个体。当然,我们只能限定在这个范围内感染,否则是不行的。

来看看全部代码:

 1 public class CountIslands {
 2     public static int countIslands(int[][] arr) {
 3         if (arr == null || arr[0] == null) {
 4             return 0;
 5         }
 6         int result = 0;
 7         int row = arr.length;
 8         int col = arr[0].length;
 9         for (int i = 0; i < row; ++i) {
10             for (int j = 0; j < col; ++j) {
11                 if (arr[i][j] == 1) {
12                     ++result;
13                     infect(arr, i, j, row, col);
14                 }
15             }
16         }
17         return result;
18     }
19 
20     private static void infect(int[][] arr, int i, int j, int row, int col) {
21         //i是行,j是列
22         if (i < 0 || i >= row || j < 0 || j >= col || arr[i][j] != 1) {
23             return;
24         }
25         arr[i][j] = 2;
26         infect(arr, i + 1, j, row, col);
27         infect(arr, i - 1, j, row, col);
28         infect(arr, i, j + 1, row, col);
29         infect(arr, i, j - 1, row, col);
30     }
31 
32     public static void main(String[] args) {
33         int[][] m = {
34                 {0, 1, 1, 0, 1, 0, 0},
35                 {1, 1, 0, 0, 0, 1, 0},
36                 {0, 0, 1, 0, 0, 1, 1},
37                 {1, 0, 1, 0, 1, 0, 1},
38                 {0, 1, 1, 1, 0, 0, 0},
39                 {1, 1, 0, 0, 0, 1, 0},
40                 {0, 0, 1, 0, 0, 1, 0},
41         };
42         System.out.println("岛的数量:" + countIslands(m));
43     }
44 }

 

posted @ 2021-08-30 16:33  EvanTheBoy  阅读(36)  评论(0编辑  收藏  举报