diff --git a/graph-bfs-dns/695.md b/graph-bfs-dns/695.md index 7d81095..63a2f00 100644 --- a/graph-bfs-dns/695.md +++ b/graph-bfs-dns/695.md @@ -1,6 +1,161 @@ -- 問題: []() -- コメント集: [](https://docs.google.com/document/d/11HV35ADPo9QxJOpJQ24FcZvtvioli770WWdZZDaLOfg/mobilebasic#h.o0jquy48e6cy) +- 問題: [695. Max Area of Island](https://leetcode.com/problems/max-area-of-island/description/) +- コメント集: [695. Max Area of Island](https://docs.google.com/document/d/11HV35ADPo9QxJOpJQ24FcZvtvioli770WWdZZDaLOfg/mobilebasic#h.o0jquy48e6cy) + - 先にQueueに詰めてしまう方針はなるほどと思った + - Taple, Java でいう Record を使う方法が出てきたが今回のような短い処理であれば不要だと考える。もう少し長い処理なら変数を明示的にかけるので良い気がする。 - 条件 -- 方針1 -- 時間計算量: -- 空間計算量: + - `m == grid.length` + - `n == grid[i].length` + - `1 <= m, n <= 50` + - `grid[i][j] is either 0 or 1.` +- 方針 + - DFS + - number of island の方針と大体同じ + - 二重ループで grid を走査、この時点で`1` or `0` 以外を含んでいた場合、`IllegalArgumentException()`を投げる + - また、引数 grid を変更するのは呼び出し者の意図に反するため、状態管理用のboolリストを用意して状態管理を切り出す + - `grid[row][index] == land`なら、その地点から上下左右を深さ優先で探索する + - 探索開始地点カウントを1として、上下左右で見つけた島の数をコールスタックが戻ってきた時に足し合わせて最後に返却する + - 時間計算量: O(m*n) + - 空間計算量: O(m*n) + - スタックメモリを使うのでスタックオーバーフローに注意する + - BFS + - DFSと同じ、探索の方法でQueueを使うだけ + - 時間計算量: O(m*n) + - 空間計算量: O(m*n) + - ヒープメモリを使う + - 感想 + - 今回の問題は個人的にはDFSの方が書きやすい + - が、過去にリプレイス案件で既存実装を読んだコードで、「なんでこの処理を再帰関数で書いてんの?!?!ああ、、これ自分にしか読めないコードをわざわざ書いて自分にしかわからない領域を作ろうとしたっぽく見えるぞ、、SEWの風上にもおけん」と思ったこともあり、、、 + - 何でもかんでも再帰関数で書くとコードリーディングは大変になると思っていて、以下のような場合でしか使わないようにしたい + - 今回のようなDFSの意図が分かりやすい問題 + - 全経路探索 + - 反対にBFSは最短経路を見つけることに特化しているので、DFS,BFSのメリデメと使いどきを常に考えていたい + +## DFS + +```java +class Solution { + public int maxAreaOfIsland(int[][] grid) { + boolean[][] visited = new boolean[grid.length][grid[0].length]; + int maxAreaOfIslands = 0; + + for (int rowIndex = 0; rowIndex < grid.length; rowIndex++) { + for (int columnIndex = 0; columnIndex < grid[0].length; columnIndex++) { + int element = grid[rowIndex][columnIndex]; + + // if element is not land or water. + if (element != 1 && element != 0) { + throw new IllegalArgumentException("grid array must contains 0 or 1"); + } + + // if element is land. + if (element == 1) { + maxAreaOfIslands = Math.max( + maxAreaOfIslands, + countNumberOfIslands(grid, visited, rowIndex, columnIndex) + ); + } + } + } + + return maxAreaOfIslands; + } + + private int countNumberOfIslands(int[][] grid, boolean[][] visited, int rowIndex, int columnIndex) { + // index out of range + if (rowIndex < 0 || columnIndex < 0 || rowIndex >= grid.length || columnIndex >= grid[0].length) { + return 0; + } + + // find water + if (grid[rowIndex][columnIndex] == 0 || visited[rowIndex][columnIndex]) { + return 0; + } + + visited[rowIndex][columnIndex] = true; + int areaOfIslands = 1; + // count top + areaOfIslands += countNumberOfIslands(grid, visited, rowIndex - 1, columnIndex); + // count bottom + areaOfIslands += countNumberOfIslands(grid, visited, rowIndex + 1, columnIndex); + // count left + areaOfIslands += countNumberOfIslands(grid, visited, rowIndex, columnIndex - 1); + // count right + areaOfIslands += countNumberOfIslands(grid, visited, rowIndex, columnIndex + 1); + + return areaOfIslands; + } +} +``` +## BFS +```java +class Solution { + public int maxAreaOfIsland(int[][] grid) { + boolean[][] visited = new boolean[grid.length][grid[0].length]; + int maxAreaOfIsland = 0; + + for (int rowIndex = 0; rowIndex < grid.length; rowIndex++) { + for (int columnIndex = 0; columnIndex < grid[0].length; columnIndex++) { + int element = grid[rowIndex][columnIndex]; + + if (element != 0 && element != 1) { + throw new IllegalArgumentException("grid array must contains 0 or 1"); + } + + // find land + if (element == 1 && !visited[rowIndex][columnIndex]) { + Queue lands = new ArrayDeque<>(); + int areaOfIslands = 0; + lands.add(new int[]{rowIndex, columnIndex}); + visited[rowIndex][columnIndex] = true; + while (!lands.isEmpty()) { + areaOfIslands++; + int[] index = lands.poll(); + int currentRowIndex = index[0]; + int currentColumnIndex = index[1]; + + int nextRowIndex = currentRowIndex + 1; + int previousRowIndex = currentRowIndex - 1; + int nextColumnIndex = currentColumnIndex + 1; + int previousColumnIndex = currentColumnIndex - 1; + + // count top + if (previousRowIndex >= 0 + && grid[previousRowIndex][currentColumnIndex] == 1 + && !visited[previousRowIndex][currentColumnIndex] + ) { + visited[previousRowIndex][currentColumnIndex] = true; + lands.add(new int[]{previousRowIndex,currentColumnIndex}); + } + // count bottom + if (nextRowIndex < grid.length + && grid[nextRowIndex][currentColumnIndex] == 1 + && !visited[nextRowIndex][currentColumnIndex] + ) { + visited[nextRowIndex][currentColumnIndex] = true; + lands.add(new int[]{nextRowIndex, currentColumnIndex}); + } + // count left + if (previousColumnIndex >= 0 + && grid[currentRowIndex][previousColumnIndex] == 1 + && !visited[currentRowIndex][previousColumnIndex] + ) { + visited[currentRowIndex][previousColumnIndex] = true; + lands.add(new int[]{currentRowIndex, previousColumnIndex}); + } + // count right + if (nextColumnIndex < grid[0].length + && grid[currentRowIndex][nextColumnIndex] == 1 + && !visited[currentRowIndex][nextColumnIndex]) { + visited[currentRowIndex][nextColumnIndex] = true; + lands.add(new int[]{currentRowIndex, nextColumnIndex}); + } + } + maxAreaOfIsland = Math.max(maxAreaOfIsland, areaOfIslands); + } + } + } + + return maxAreaOfIsland; + } +} +``` \ No newline at end of file