-
Notifications
You must be signed in to change notification settings - Fork 0
Graph bfs dfs 200 #17
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,131 @@ | ||
| - 問題: []() | ||
| - コメント集: [](https://docs.google.com/document/d/11HV35ADPo9QxJOpJQ24FcZvtvioli770WWdZZDaLOfg/mobilebasic#h.o0jquy48e6cy) | ||
| - 問題: [200. Number of Islands](https://leetcode.com/problems/number-of-islands/submissions/2008160365/) | ||
| - コメント集: [200. Number of Islands](https://docs.google.com/document/d/11HV35ADPo9QxJOpJQ24FcZvtvioli770WWdZZDaLOfg/mobilebasic#h.o0jquy48e6cy) | ||
| - 一応全て確認したが、Python関係の話が多かったと思う | ||
| - コメント先のPullRequestで、column, row の変数名の話と引数を変更するのはどうなんだ?という話があったので考えてみた | ||
|
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. 考えてみた内容か、それを踏まえたコードがあると良いと思います。 |
||
| - 条件 | ||
| - m == grid.length | ||
| - n == grid[i].length | ||
| - 1 <= m, n <= 300 | ||
| - grid[i][j] is '0' or '1'. | ||
| - 方針1 | ||
| - 時間計算量: | ||
| - 空間計算量: | ||
| - grid に対して二重ループを回しながら1件ずつ走査する | ||
| - 走査の過程で、`grid[column][row]` が land の場合、隣接する land を全て water に変更するような処理を再帰関数(dfs)で組む | ||
| - DFSのイメージ: 行けるところまで深く潜って戻ってきてね | ||
| - DFSのユースケース: 全部探索, `find`コマンドで目的のファイルを探すなどが該当する | ||
| - 方針2 | ||
| - grid に対して二重ループを回しながら1件ずつ走査する | ||
| - 基本的にはDFSと同じだが、`queue`を使って波紋が広がるように調べていく点が少し違う | ||
| - BFSのイメージ: 波紋が広がるように、起点から調べていく. DFSとの差分でいうと、最初に到達した探索結果が必ず最短が保証されている.なぜかというと、Queueに順序付きQueueを使っており、挿入した順序が必ず守られているから | ||
| - BFSのユースケース: マップの最短経路探索 | ||
| - 時間計算量: `O(m*n)` | ||
| - 空間計算量: `O(m*n)` --> 最悪、全ての要素がコールスタックに乗ることになる, BFSは全ての要素がQueueにのることになる | ||
|
|
||
| ## DFS | ||
| - 20分 | ||
| ```java | ||
| class Solution { | ||
| public int numIslands(char[][] grid) { | ||
| if (grid.length == 0) return 0; | ||
|
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. こちらのコメントをご参照ください。 |
||
|
|
||
| int result = 0; | ||
| for (int rowIndex = 0; rowIndex < grid.length; rowIndex++) { | ||
| for (int columnIndex = 0; columnIndex < grid[0].length; columnIndex++) { | ||
| result += numIslandsHelper(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. この関数に返り値はなくてもいいかなと思いました。島があるかないかで1か0が返ってくるだけなので。
Owner
Author
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. おっしゃる通りですね。 |
||
| } | ||
| } | ||
|
|
||
| return result; | ||
| } | ||
|
|
||
| private int numIslandsHelper(char[][] grid, 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. このメソッドは、numIslandsHelperと名付けるにはnumIslandsと違いすぎると思いました。返り値も0か1だけですし。 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の書き換えも行なっているのでそれがわかるようにしたいですね。
Owner
Author
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. お二人ともありがとうございます、 |
||
| // index ouf of range | ||
| if ((rowIndex < 0 || columnIndex < 0) || (rowIndex >= grid.length || columnIndex >= grid[0].length)) { | ||
|
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 (!(0 <= rowIndex && rowIndex < grid.length && 0 <= columnIndex && columnIndex < grid[0].length)) { |
||
| return 0; | ||
| } | ||
| // find water | ||
| if (grid[rowIndex][columnIndex] == '0') { | ||
| return 0; | ||
| } | ||
| // find land | ||
| if (grid[rowIndex][columnIndex] == '1') { | ||
| grid[rowIndex][columnIndex] = '0'; | ||
|
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. こちらのコメントをご参照ください。 |
||
| // seach top, left, right, bottom of this land | ||
| // find top | ||
| numIslandsHelper(grid, rowIndex - 1, columnIndex); | ||
| // find bottom | ||
| numIslandsHelper(grid, rowIndex + 1, columnIndex); | ||
| // find left | ||
| numIslandsHelper(grid, rowIndex, columnIndex - 1); | ||
| // find right | ||
| numIslandsHelper(grid, rowIndex, columnIndex + 1); | ||
|
|
||
| return 1; | ||
| } | ||
|
|
||
| throw new IllegalArgumentException("The argument grid[][] contained a character other than 0 or 1"); | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| ## BFS | ||
| ```java | ||
| class Solution { | ||
| public int numIslands(char[][] grid) { | ||
| if (grid.length == 0) return 0; | ||
|
|
||
| int result = 0; | ||
| for (int rowIndex = 0; rowIndex < grid.length; rowIndex++) { | ||
| for (int columnIndex = 0; columnIndex < grid[0].length; columnIndex++) { | ||
| result += numIslandsHelper(grid, rowIndex, columnIndex); | ||
| } | ||
| } | ||
|
|
||
| return result; | ||
| } | ||
|
|
||
| private int numIslandsHelper(char[][] grid, int rowIndex, int columnIndex) { | ||
| Queue<int[]> lands = new ArrayDeque<>(); | ||
|
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. int[]ではなくrecordを使う選択肢もあると思います。
Owner
Author
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. 可読性を考えるとおっしゃる通りかと。 |
||
| // find land | ||
| if (grid[rowIndex][columnIndex] == '1') { | ||
|
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. もう少しシンプルに early return したほうが、読み手にとって読みやすくなると思います。 if (grid[rowIndex][columnIndex] == '0') {
return 0;
}
grid[rowIndex][columnIndex] = '0';
lands.add(new int[]{rowIndex, columnIndex}); |
||
| grid[rowIndex][columnIndex] = '0'; | ||
| lands.add(new int[]{rowIndex, columnIndex}); | ||
| } else { | ||
| return 0; | ||
| } | ||
|
|
||
| while (!lands.isEmpty()) { | ||
| int[] index = lands.poll(); | ||
|
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. 細かいかもしれませんが、キューへの追加と削除についてadd/pollを使っていますが、add/removeかoffer/pollのどちらかだけを使う方が統一感があり好みです。
Owner
Author
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. コメントありがとうございます、読みました。 私の認識で恐縮ですが、どちらかというと、例外投げて欲しければ add/remove, 例外ではなく値が欲しいなら offer/poll を使おうということで、文脈に応じて使い分けるものかなと思っているのですが、どうでしょう? 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. すみません、そうですね。間違って覚えていました……。 |
||
| int numRow = index[0]; | ||
|
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. 考えているかもしれませんが、この変数名は見づらく感じました。numと付くと「rowの個数」のように見えるからです。 |
||
| int numColumn = index[1]; | ||
|
|
||
| // 上下左右を探索して、1ならqueueにつめる | ||
| int nextNumRow = numRow + 1; | ||
|
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. これは変数に置かないほうが直接的で見やすいと感じました。 |
||
| int previousNumRow = numRow - 1; | ||
| int nextNumColumn = numColumn + 1; | ||
| int previousNumColumn = numColumn - 1; | ||
| // top | ||
| if (previousNumRow >= 0 && grid[previousNumRow][numColumn] == '1') { | ||
| grid[previousNumRow][numColumn] = '0'; | ||
| lands.add(new int[]{previousNumRow, numColumn}); | ||
| } | ||
| // bottom | ||
| if (nextNumRow < grid.length && grid[nextNumRow][numColumn] == '1') { | ||
| grid[nextNumRow][numColumn] = '0'; | ||
| lands.add(new int[]{nextNumRow, numColumn}); | ||
| } | ||
| // left | ||
| if (previousNumColumn >= 0 && grid[numRow][previousNumColumn] == '1') { | ||
| grid[numRow][previousNumColumn] = '0'; | ||
| lands.add(new int[]{numRow, previousNumColumn}); | ||
| } | ||
| // right | ||
| if (nextNumColumn < grid[0].length && grid[numRow][nextNumColumn] == '1') { | ||
| grid[numRow][nextNumColumn] = '0'; | ||
| lands.add(new int[]{numRow, nextNumColumn}); | ||
| } | ||
| } | ||
|
|
||
| return 1; | ||
| } | ||
| } | ||
| ``` | ||
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.
コメント集にあったか覚えてないですが、今回は与えられた配列を破壊するべきかしないべきかの検討があってもいいと思いました。
例えば、何か島を作る関数が別であった時などにデバッグで使うを想定すると、今回は引数で与えられた配列は破壊したくないですね
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.
ありがとうございます。
ここ、対応しようと思って忘れてました。
取り込みます。