题目及测试
package pid200;
/* 岛屿的个数
给定一个由 '1'(陆地)和 '0'(水)组成的的二维网格,计算岛屿的数量。一个岛被水包围,并且它是通过水平方向或垂直方向上相邻的陆地连接而成的。你可以假设网格的四个边均被水包围。
示例 1:
输入:
11110
11010
11000
00000
输出: 1
示例 2:
输入:
11000
11000
00100
00011
输出: 3
*/
import java.util.List;
public class main {
public static void main(String[] args) {
char[][] testTable = {{'1','1','0','0','0'},{'1','1','0','0','0'},
{'0','0','1','0','0'},{'0','0','0','1','1'}};
test(testTable);
}
private static void test(char[][] ito) {
Solution solution = new Solution();
int rtn;
long begin = System.currentTimeMillis();
for(char[] now:ito){
for(char nowc:now){
System.out.print(nowc+" ");
}
System.out.println();
}
System.out.println();
//开始时打印数组
rtn= solution.numIslands(ito);//执行程序
long end = System.currentTimeMillis();
System.out.println("rtn=" );
System.out.print(rtn);
System.out.println();
System.out.println("耗时:" + (end - begin) + "ms");
System.out.println("-------------------");
}
}
解法1(成功,4ms,较快)
设置hasGone二维数组,使用深度优先遍历,将周围是1的都遍历到,并且设置hasGone为true。
从主方法开始,遍历过几次,就有几个岛屿(因为遍历第一个岛屿,会将岛屿所有连接的地方都设为true,那些地方不会再从主方法遍历)
public int numIslands(char[][] grid) {
int rows=grid.length;
if(rows==0){
return 0;
}
int cols=grid[0].length;
if(cols==0){
return 0;
}
int result=0;
boolean[][] hasGone=new boolean[rows][cols];
for(int i=0;i<rows;i++){
for(int j=0;j<cols;j++){
// 如果为陆地而且没有被遍历过,遍历,并且岛屿数量++
if(grid[i][j]=='1'&&hasGone[i][j]==false){
dfsGo(i, j, rows, cols, grid, hasGone);
result++;
}
}
}
return result;
}
public void dfsGo(int i,int j,int rows,int cols,char[][] grid,boolean[][] hasGone){
// 进入这个方法,代表这个地方可以被遍历
hasGone[i][j]=true;
//上
if(j>0){
if(grid[i][j-1]=='1'&&hasGone[i][j-1]==false){
dfsGo(i, j-1, rows, cols, grid, hasGone);
}
}
//下
if(j+1<cols){
if(grid[i][j+1]=='1'&&hasGone[i][j+1]==false){
dfsGo(i, j+1, rows, cols, grid, hasGone);
}
}
//左
if(i>0){
if(grid[i-1][j]=='1'&&hasGone[i-1][j]==false){
dfsGo(i-1, j, rows, cols, grid, hasGone);
}
}
//右
if(i+1<rows){
if(grid[i+1][j]=='1'&&hasGone[i+1][j]==false){
dfsGo(i+1, j, rows, cols, grid, hasGone);
}
}
}
解法2(别人的)
采用深度优先遍历,把访问过的改为‘0’,继续遍历。
思路一样,减少空间
public class 岛屿的数量 {
public int numIslands(char[][] grid) {
if (grid == null || grid.length == 0
|| grid[0].length == 0)
return 0;
int rows = grid.length;
int cols = grid[0].length;
int count = 0;
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++)
// 注意char
if (grid[i][j] == '1') {
count++;
dfsSearch(grid, i, j, rows, cols);
}
return count++;
}
// 每遇到'1'后, 开始向四个方向 递归搜索. 搜到后变为'0',
// 因为相邻的属于一个island. 然后开始继续找下一个'1'.
private void dfsSearch(char[][] grid,
int i, int j, int rows, int cols) {
if (i < 0 || i >= rows || j < 0 || j >= cols)
return;
if (grid[i][j] != '1')
return;
// 也可以才用一个visited数组,标记遍历过的岛屿
grid[i][j] = '0';
dfsSearch(grid, i + 1, j, rows, cols);
dfsSearch(grid, i - 1, j, rows, cols);
dfsSearch(grid, i, j + 1, rows, cols);
dfsSearch(grid, i, j - 1, rows, cols);
}
}
解法3(别人的)
并查集
class Solution {
class UnionFind {
int count; // # of connected components
int[] parent;
int[] rank;
public UnionFind(char[][] grid) { // for problem 200
count = 0;
int m = grid.length;
int n = grid[0].length;
parent = new int[m * n];
rank = new int[m * n];
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
if (grid[i][j] == '1') {
parent[i * n + j] = i * n + j;
++count;
}
rank[i * n + j] = 0;
}
}
}
public int find(int i) { // path compression
if (parent[i] != i) parent[i] = find(parent[i]);
return parent[i];
}
public void union(int x, int y) { // union with rank
int rootx = find(x);
int rooty = find(y);
if (rootx != rooty) {
if (rank[rootx] > rank[rooty]) {
parent[rooty] = rootx;
} else if (rank[rootx] < rank[rooty]) {
parent[rootx] = rooty;
} else {
parent[rooty] = rootx; rank[rootx] += 1;
}
--count;
}
}
public int getCount() {
return count;
}
}
public int numIslands(char[][] grid) {
if (grid == null || grid.length == 0) {
return 0;
}
int nr = grid.length;
int nc = grid[0].length;
int num_islands = 0;
UnionFind uf = new UnionFind(grid);
for (int r = 0; r < nr; ++r) {
for (int c = 0; c < nc; ++c) {
if (grid[r][c] == '1') {
grid[r][c] = '0';
if (r - 1 >= 0 && grid[r-1][c] == '1') {
uf.union(r * nc + c, (r-1) * nc + c);
}
if (r + 1 < nr && grid[r+1][c] == '1') {
uf.union(r * nc + c, (r+1) * nc + c);
}
if (c - 1 >= 0 && grid[r][c-1] == '1') {
uf.union(r * nc + c, r * nc + c - 1);
}
if (c + 1 < nc && grid[r][c+1] == '1') {
uf.union(r * nc + c, r * nc + c + 1);
}
}
}
}
return uf.getCount();
}
}