-
Notifications
You must be signed in to change notification settings - Fork 0
Graph bfs dfs 695 #18
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. この関数名だと grid 内の島の数を数えているように見えました。 |
||
| // 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]; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
|
|
||
| if (element != 0 && element != 1) { | ||
| throw new IllegalArgumentException("grid array must contains 0 or 1"); | ||
| } | ||
|
|
||
| // find land | ||
| if (element == 1 && !visited[rowIndex][columnIndex]) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Step1 みたいに、探索の処理は関数に切り出した方が読みやすいと思いました |
||
| Queue<int[]> 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}); | ||
| } | ||
|
Comment on lines
+121
to
+128
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. この処理は4回くり返し書くにはちょっと長く感じました。メソッドに切り出す、長さ4の配列を作りループする、など対処法がコメント集にあったと思うので、見ていなければ見てみると参考になるかもしれません。 |
||
| // 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; | ||
| } | ||
| } | ||
| ``` | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
0, 1は water, land のような定数にした方が扱いやすいと思いました。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
そうすれば
if (element == land)のように書くことができ、可読性があがるので// if element is land.のようなコメントを削れると思います