二维数组寻找小岛
有这样一道题:

是不是看起来很复杂,昨天听了左神讲的课,他用了一个简单的算法,时间复杂度只有O(N*M)数组长度那么少!
一开始看这个题,没有什么思路,想着这个题时间复杂都肯定很高吧!直到最后才发现,卧槽,还有这种操作!!!!
话不多说,直接上自己的代码!
public class Main { public static int countIslands(int[][] m) { //判断2维数组合法 if (m == null || m[0] == null) { return 0; } int N = m.length; int M = m[0].length; //res标记为1的元素,统计个数。 int res = 0; //如果发现为1的元素,就去感染他周围(山下左右)的元素 for (int i = 0; i < N; i++) { for (int j = 0; j < M; j++) { if (m[i][j] == 1) { res++; infect(m, i, j, N, M); } } } return res; } //感染方法 public static void infect(int[][] m, int i, int j, int N, int M) { //元素下标越界或!=1退出 if (i < 0 || i >= N || j < 0 || j >= M || m[i][j] != 1) { return; } m[i][j] = 2; /*小技巧:找到1之后标记为2,(随便标记一个数就行)表示这个位置元素不再会被感染。 * 为什么呢?数组在遍历时碰到1,就会将1变为2,感染周围为1的元素,周围元素继续由1变2感染各自的周围为1的元素,依此递归, 直到一个岛的元素都被感染,被0包围,无法继续感染,退出递归,res++表示找到了一个岛。 这时就要继续从开始发现1的下一个位置开始继续遍历,由于我们把感染的元素都变为了2,所以就不再去调用infect感染方法了。 直到找到一个未感染(元素都为1)的新岛。依次遍历,当数组完成一次遍历,所有的岛都会被感染,就会找到所有的岛。 时间复杂度为O(N*M).*/ //递归感染周围元素 infect(m, i + 1, j, N, M);//上 infect(m, i - 1, j, N, M);//下 infect(m, i, j - 1, N, M);//作 infect(m, i, j + 1, N, M);//右 } public static void main(String[] args) { int[][] m1 = { { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 1, 1, 1, 0, 1, 1, 1, 0 }, { 0, 1, 1, 1, 0, 0, 0, 1, 0 }, { 0, 1, 1, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 1, 1, 0, 0 }, { 0, 0, 0, 0, 1, 1, 1, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, }; System.out.println(countIslands(m1)); int[][] m2 = { { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 1, 1, 1, 1, 1, 1, 1, 0 }, { 0, 1, 1, 1, 0, 0, 0, 1, 0 }, { 0, 1, 1, 0, 0, 0, 1, 1, 0 }, { 0, 0, 0, 0, 0, 1, 1, 0, 0 }, { 0, 0, 0, 0, 1, 1, 1, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, }; System.out.println(countIslands(m2)); } }
具体思路代码中注释写的很清楚,主要步骤是:
1 遍历二维数组
2 找到为1的元素标记
3递归感染周围为1的元素
是不是很爽,只有O(N*M)的时间复杂度。。。
并行计算,会使运行速度极大提高!至于如何使用并行计算,有以下思路,代码还没实现:
比如2个处理器并行计算,就把这个组分为2块,运用并查集的思想(大家可以细细研究下)和上述查找方法,并行查找。
最后在把边界公共的小岛(图中所示的红圈部分)合并就ok了。
如下图所示:

浙公网安备 33010602011771号