All reachable problem ---island
https://leetcode.com/problems/number-of-islands
Island problem, 可以是一张图上,1)flood fill, 2) number of islands, 3) max area of the island
Question
Given an m x n
2D binary grid grid
which represents a map of '1'
s (land) and '0'
s (water), return the number of islands.
An island is surrounded by water and is formed by connecting adjacent lands horizontally or vertically. You may assume all four edges of the grid are all surrounded by water.
Clarification & Assumption
Graph Representation
vertex: 所有是“1” 的点
edge: four directions 为 “1” 的点
High Level
Problem definition
this is an all-reachable nodes problem
starting from every 1 vertex, traversing all connected element
What traversal algorithm?
DFS1, DFS2, DFS3(for each vertex, traverse all possible reachable vertex, by depth order, and make sure each vertex visited once)
BFS(for each vertex, traverse all possible reachable vertex, by level/breath order, and make sure each vertex visited once)
Middle Level
Graph representation?
Method 1: 完全分开
graph representation
vertex, int[][]
edge: four direction {-1, 0} {1, 0}, {0, -1}, {0, 1}
visited: boolean visited[][]
Method 2: 把visited单独出来
graph representation
Vertex: cell (int x, int y)
edge: four direction {-1, 0} {1, 0}, {0, -1}, {0, 1}:
visited: enum / boolean visited[][]
Method 3: 全部合在一起
Graph Representation, vertex & edge together
Vertex& Edge
Graph
Node {int x, int y, int value, boolean visited, Set<Vertex> neighb}
TC & SC
TC: O(|V| + |E|) = O (5mn), SC: O(mn)
Method 1 DFS
class Solution {
private static final int[][] DIRS = new int[][] {{-1, 0}, {0, -1}, {1, 0}, {0, 1}};
public int numIslands(char[][] grid) {
if (grid == null || grid.length == 0 || grid[0].length == 0) {
return 0;
}
boolean[][] visited = new boolean[grid.length][grid[0].length];
int count = 0;
for (int i = 0; i < grid.length; i++) {
for (int j = 0; j < grid[0].length; j++) {
if (visited[i][j] == false && grid[i][j] == '1') {
dfs(grid, i, j, visited);
count++;
}
}
}
return count;
}
private void dfs(char[][] grid, int row, int col, boolean[][] visited) {
// // check visited
if (!isValid(grid, row, col) || visited[row][col] || grid[row][col] != '1') {
return;
}
// mark visited
visited[row][col] = true;
// visiting neighbor
for (int[] dir : DIRS) {
int neiX = row + dir[0];
int neiY = col + dir[1];
dfs(grid, neiX, neiY, visited);
}
}
private boolean isValid(char[][] grid, int row, int col) {
return row >= 0 && row < grid.length && col >= 0 && col < grid[0].length;
}
}
Method 1 BFS (& DFS)
class Solution {
class Cell {
int x;
int y;
public Cell (int x, int y) {
this.x = x;
this.y = y;
}
public int hashCode() {
return this.x * 31 + this.y;
}
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null) return false;
if (this.getClass() != obj.getClass()) {
return false;
}
Cell that = (Cell)obj;
return this.x == that.x && this.y == that.y;
}
}
public int numIslands(char[][] grid) {
//sanity check
if (grid == null || grid.length == 0 || grid[0].length == 0) {
return 0;
}
// build graph
// build visited check
boolean[][] visited = new boolean[grid.length][grid[0].length];
// bfs && dfs
// initial
// expand & generate
int[] count = new int[1];
for (int x = 0; x < grid.length; x++) {
for (int y = 0; y < grid[0].length; y++) {
if (grid[x][y] == '1' && visited[x][y] == false) {
Cell root = new Cell(x, y);
// bfs(grid, visited, root);
dfs(grid, visited, root);
count[0]++;
}
}
}
return count[0];
}
private void dfs (char[][] grid, boolean[][] visited, Cell root) {
if (!isValid(root.x, root.y, grid) || visited[root.x][root.y] || grid[root.x][root.y] != '1') {
return;
}
visited[root.x][root.y] = true;
for (int[] dir : DIRT) {
int neiX = root.x + dir[0];
int neiY = root.y + dir[1];
Cell nei = new Cell(neiX, neiY);
dfs(grid, visited, nei);
}
}
private void bfs (char[][] grid, boolean[][] visited, Cell root) {
Queue<Cell> queue = new ArrayDeque<>();
queue.offer(root);
visited[root.x][root.y] = true;
while (!queue.isEmpty()) {
int size = queue.size();
for (int i = 0; i < size; i++) {
Cell cur = queue.poll();
for (int[] dir: DIRT) {
int neiX = cur.x + dir[0];
int neiY = cur.y + dir[1];
Cell nei = new Cell(neiX, neiY);
if (isValid(neiX, neiY, grid) && grid[neiX][neiY] == '1' && visited[neiX][neiY] == false) {
queue.offer(nei);
visited[nei.x][nei.y] = true;
}
}
}
}
}
private boolean isValid (int x, int y, char[][] grid) {
return x >= 0 && x < grid.length && y >=0 && y < grid[0].length;
}
private static final int[][] DIRT = new int[][] {{-1, 0}, {1, 0}, {0, 1}, {0, -1}};
}
Method 3 BFS & DFS
class Solution {
class Vertex {
int x;
int y;
Set<Vertex> neighbors;
boolean visited;
char value;
public Vertex(int x, int y, char value) {
this.x = x;
this.y = y;
this.neighbors = new HashSet<>();
this.visited = false;
this.value = value;
}
@Override
public int hashCode() {
return this.x * 31 + this.y;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null) return false;
if (this.getClass() != obj.getClass()) {
return false;
}
Vertex that = (Vertex) obj;
return this.x == that.x && this.y == that.y;
}
}
public int numIslands(char[][] grid) {
// sanity check
// buildGraph
Set<Vertex> graph = buildGraph(grid);
// traverse
int count = 0;
for (Vertex root: graph) {
if (isValid(root.x, root.y, grid) && root.value == '1' && root.visited != true) {
// bfs(root, graph, grid);
dfs(root, graph, grid);
count++;
}
}
return count;
}
private void bfs(Vertex root, Set<Vertex> graph, char[][] grid) {
Queue<Vertex> queue = new ArrayDeque<>();
queue.offer(root);
root.visited = true;
while (!queue.isEmpty()) {
int size = queue.size();
for (int i = 0; i < size; i++) {
Vertex cur = queue.poll();
for (Vertex nei: cur.neighbors) {
if (isValid(nei.x, nei.y, grid) && nei.visited != true && nei.value == '1') {
queue.offer(nei);
nei.visited = true;
}
}
}
}
}
private void dfs(Vertex root, Set<Vertex> graph, char[][] grid) {
// base case
if (root.visited == true) {
return;
}
// cur step visited?
root.visited = true;
for (Vertex nei: root.neighbors) {
if (isValid(nei.x, nei.y, grid) && nei.value == '1') {
dfs(nei, graph, grid);
}
}
//
}
private Set<Vertex> buildGraph(char[][] grid) {
Set<Vertex> graph = new HashSet<>();
for (int x = 0; x < grid.length; x++) {
for (int y = 0; y < grid[0].length; y++) {
Vertex cur = new Vertex(x, y, grid[x][y]);
graph.add(cur);
}
}
for (Vertex vertex: graph) {
for (int[] dir: DIRT) {
int neiX = vertex.x + dir[0];
int neiY = vertex.y + dir[1];
if (isValid(neiX, neiY, grid)) {
for (Vertex nei: graph) {
if (nei.x == neiX && nei.y == neiY) {
vertex.neighbors.add(nei);
}
}
}
}
}
return graph;
}
private boolean isValid(int x, int y, char[][] grid) {
return x >= 0 && x < grid.length && y >= 0 && y < grid[0].length;
}
private static final int[][] DIRT = new int[][]{{-1, 0},{1, 0}, {0,1}, {0, -1}};
}
Method 2 DFS & BFS for maximum area of island
Last updated