My code:
public class Solution {
private int count = 0;
private int width = 0;
private int height = 0;
public int numIslands(char[][] grid) {
if (grid == null || grid.length == 0 || grid[0].length == 0)
return 0;
boolean[][] isVisited = new boolean[grid.length][grid[0].length];
width = grid[0].length;
height = grid.length;
int count = 0;
for (int i = 0; i < grid.length; i++) {
for (int j = 0; j < grid[0].length; j++) {
if (!isVisited[i][j] && grid[i][j] == '1') {
count++;
dfs(grid, isVisited, i, j);
}
}
}
return count;
}
private void dfs(char[][] grid, boolean[][] isVisited, int i, int j) {
if (!isValidLocation(i, j) || isVisited[i][j] || grid[i][j] == '0')
return;
isVisited[i][j] = true;
dfs(grid, isVisited, i - 1, j);
dfs(grid, isVisited, i + 1, j);
dfs(grid, isVisited, i, j - 1);
dfs(grid, isVisited, i, j + 1);
}
private boolean isValidLocation(int i, int j) {
if (i < 0 || i >= height)
return false;
else if (j < 0 || j >= width)
return false;
else
return true;
}
}
这是dfs版本。
这道题目可以用三种方法写。
dfs, bfs, union-find
花了挺多时间。
dfs:
My code:
public class Solution {
private int row = 0;
private int col = 0;
private int[][] dir = new int[][]{{0, -1}, {0, 1}, {-1, 0}, {1, 0}};
public int numIslands(char[][] grid) {
if (grid == null || grid.length == 0 || grid[0].length == 0) {
return 0;
}
int counter = 0;
this.row = grid.length;
this.col = grid[0].length;
boolean[][] mark = new boolean[grid.length][grid[0].length];
for (int i = 0; i < grid.length; i++) {
for (int j = 0; j < grid[0].length; j++) {
if (!mark[i][j] && grid[i][j] == '1') {
counter++;
dfs(i, j, grid, mark);
}
}
}
return counter;
}
private void dfs(int i, int j, char[][] grid, boolean[][] mark) {
mark[i][j] = true;
for (int k = 0; k < 4; k++) {
int curr_r = i + dir[k][0];
int curr_c = j + dir[k][1];
if (check(curr_r, curr_c) && !mark[curr_r][curr_c] && grid[curr_r][curr_c] == '1') {
dfs(curr_r, curr_c, grid, mark);
}
}
}
private boolean check(int i, int j) {
if (i < 0 || i >= row || j < 0 || j >= col) {
return false;
}
return true;
}
public static void main(String[] args) {
Solution test = new Solution();
char[][] input = new char[4][5];
input[0] = "11110".toCharArray();
input[1] = "11010".toCharArray();
input[2] = "11000".toCharArray();
input[3] = "00000".toCharArray();
int ret = test.numIslands(input);
System.out.println(ret);
}
}
bfs:
My code:
public class Solution {
private int row = 0;
private int col = 0;
private int[][] dir = new int[][]{{0, -1}, {0, 1}, {-1, 0}, {1, 0}};
private class Pair {
int x;
int y;
Pair(int x, int y) {
this.x = x;
this.y = y;
}
}
public int numIslands(char[][] grid) {
if (grid == null || grid.length == 0 || grid[0].length == 0) {
return 0;
}
this.row = grid.length;
this.col = grid[0].length;
boolean[][] mark = new boolean[this.row][this.col];
int counter = 0;
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
if (grid[i][j] == '1' && !mark[i][j]) {
visit(i, j, mark, grid);
counter++;
}
}
}
return counter;
}
private void visit(int i, int j, boolean[][] mark, char[][] grid) {
Queue q = new LinkedList();
q.offer(new Pair(i, j));
while (!q.isEmpty()) {
Pair curr = q.poll();
mark[curr.x][curr.y] = true;
for (int k = 0; k < 4; k++) {
int curr_r = curr.x + dir[k][0];
int curr_c = curr.y + dir[k][1];
if (check(curr_r, curr_c) && grid[curr_r][curr_c] == '1' && !mark[curr_r][curr_c]) {
q.offer(new Pair(curr_r, curr_c));
}
}
}
}
private boolean check(int i, int j) {
if (i < 0 || i >= row || j < 0 || j >= col) {
return false;
}
return true;
}
}
这个bfs老是超时,我也不知道为什么,暂且不管了。
其实这里的bfs和dfs差不多,也得用 一个容器来标志每个节点的状态。防止重复。
下面是 Union-Find
My code:
public class Solution {
private int row = 0;
private int col = 0;
private int[][] dir = new int[][]{{0, -1}, {0, 1}, {-1, 0}, {1, 0}};
private int[] id;
private int[] size;
public int numIslands(char[][] grid) {
if (grid == null || grid.length == 0 || grid[0].length == 0) {
return 0;
}
this.row = grid.length;
this.col = grid[0].length;
id = new int[row * col];
size = new int[row * col];
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
id[i * col + j] = i * col + j;
size[i * col + j] = 1;
}
}
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
if (grid[i][j] == '1') {
visit(i, j, grid);
}
}
}
int counter = 0;
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
if (grid[i][j] == '1' && i * col + j == this.find(i * col + j)) {
counter++;
}
}
}
return counter;
}
private void visit(int i, int j, char[][] grid) {
int index = i * col + j;
for (int k = 0; k < 4; k++) {
int curr_r = i + dir[k][0];
int curr_c = j + dir[k][1];
if (check(curr_r, curr_c) && grid[curr_r][curr_c] == '1') {
union(index, curr_r * col + curr_c);
}
}
}
private boolean check(int i, int j) {
if (i < 0 || i >= row || j < 0 || j >= col) {
return false;
}
return true;
}
private int find(int i) {
if (id[i] == i) {
return i;
}
else {
int ret = find(id[i]);
id[i] = ret;
return ret;
}
}
private void union(int i, int j) {
int left = find(i);
int right = find(j);
if (left == right) {
return;
}
else {
if (size[left] < size[right]) {
id[left] = right;
size[right] += size[left];
}
else {
id[right] = left;
size[left] += size[right];
}
}
}
public static void main(String[] args) {
Solution test = new Solution();
char[][] input = new char[4][5];
input[0] = "11110".toCharArray();
input[1] = "11010".toCharArray();
input[2] = "11000".toCharArray();
input[3] = "00000".toCharArray();
int ret = test.numIslands(input);
System.out.println(ret);
}
}
趁着这个机会复习了下 Union find or called Disjoint Set
reference:
http://www.geeksforgeeks.org/disjoint-set-data-structures-java-implementation/
重点就是记住, find 的时候呢需要 compress path
然后多用一个size数组,当两个树merge的时候,小树得merge into 大树
Anyway, Good luck, Richardo! -- 09/09/2016
My code:
public class Solution {
private int row = 0;
private int col = 0;
private int[][] dir = new int[][]{{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
public int numIslands(char[][] grid) {
if (grid == null || grid.length == 0 || grid[0].length == 0) {
return 0;
}
this.row = grid.length;
this.col = grid[0].length;
UnionFind uf = new UnionFind(this.row, this.col);
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
if (grid[i][j] == '1') {
int id = uf.add(i, j);
for (int k = 0; k < 4; k++) {
int next_x = i + dir[k][0];
int next_y = j + dir[k][1];
if (check(next_x, next_y) && grid[next_x][next_y] == '1') {
int next_id = uf.find(next_x, next_y);
if (next_id > 0) {
uf.union(i, j, next_x, next_y);
}
}
}
}
}
}
return uf.counter;
}
private boolean check(int i, int j) {
if (i < 0 || i >= row || j < 0 || j >= col) {
return false;
}
else {
return true;
}
}
}
class UnionFind {
int[] ids;
int[] sz;
int row;
int col;
int counter;
UnionFind(int row, int col) {
this.row = row;
this.col = col;
ids = new int[row * col + 1];
sz = new int[row * col + 1];
counter = 0;
}
int add(int i, int j) {
int id = getId(i, j);
ids[id] = id;
counter++;
return id;
}
int find(int i, int j) {
return find(getId(i, j));
}
int find(int id) {
if (ids[id] == id) {
return id;
}
else {
int ret = find(ids[id]);
ids[id] = ret;
return ret;
}
}
void union(int i1, int j1, int i2, int j2) {
int id1 = find(i1, j1);
int id2 = find(i2, j2);
if (id1 == id2) {
return;
}
else {
counter--;
if (sz[id1] > sz[id2]) {
ids[id2] = id1;
sz[id1] += sz[id2];
}
else {
ids[id1] = id2;
sz[id2] += sz[id1];
}
}
}
int getId(int i, int j) {
return i * col + j + 1;
}
}
采用了一种比较新的方法写 Union Find
利用一个counter来记录 独立部分的个数
ids[id] = i * col + j + 1;
Anyway, Good luck, Richardo! -- 09/25/2016