From 28ebd5ae7ce0690a1cf79be7ef5d3dd4f532fd4f Mon Sep 17 00:00:00 2001 From: busker <165013324+hiroki-horiguchi-dev@users.noreply.github.com> Date: Sat, 23 May 2026 21:08:16 +0900 Subject: [PATCH 1/4] Update 695.md --- graph-bfs-dns/695.md | 161 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 157 insertions(+), 4 deletions(-) diff --git a/graph-bfs-dns/695.md b/graph-bfs-dns/695.md index 7d81095..1d2dc37 100644 --- a/graph-bfs-dns/695.md +++ b/graph-bfs-dns/695.md @@ -1,6 +1,159 @@ -- 問題: []() +- 問題: [695. Max Area of Island](https://leetcode.com/problems/max-area-of-island/description/) - コメント集: [](https://docs.google.com/document/d/11HV35ADPo9QxJOpJQ24FcZvtvioli770WWdZZDaLOfg/mobilebasic#h.o0jquy48e6cy) - 条件 -- 方針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 From 2a0e84ff5f7e1aab5c217b69178c1659e121ac93 Mon Sep 17 00:00:00 2001 From: busker <165013324+hiroki-horiguchi-dev@users.noreply.github.com> Date: Sat, 23 May 2026 23:47:39 +0900 Subject: [PATCH 2/4] =?UTF-8?q?=E3=82=B3=E3=83=A1=E3=83=B3=E3=83=88?= =?UTF-8?q?=E5=AF=BE=E5=BF=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- graph-bfs-dns/695.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/graph-bfs-dns/695.md b/graph-bfs-dns/695.md index 1d2dc37..63a2f00 100644 --- a/graph-bfs-dns/695.md +++ b/graph-bfs-dns/695.md @@ -1,5 +1,7 @@ - 問題: [695. Max Area of Island](https://leetcode.com/problems/max-area-of-island/description/) -- コメント集: [](https://docs.google.com/document/d/11HV35ADPo9QxJOpJQ24FcZvtvioli770WWdZZDaLOfg/mobilebasic#h.o0jquy48e6cy) +- コメント集: [695. Max Area of Island](https://docs.google.com/document/d/11HV35ADPo9QxJOpJQ24FcZvtvioli770WWdZZDaLOfg/mobilebasic#h.o0jquy48e6cy) + - 先にQueueに詰めてしまう方針はなるほどと思った + - Taple, Java でいう Record を使う方法が出てきたが今回のような短い処理であれば不要だと考える。もう少し長い処理なら変数を明示的にかけるので良い気がする。 - 条件 - `m == grid.length` - `n == grid[i].length` From 947fb515d0867964927a60cd761d9bf51385557f Mon Sep 17 00:00:00 2001 From: busker <165013324+hiroki-horiguchi-dev@users.noreply.github.com> Date: Sun, 24 May 2026 13:39:15 +0900 Subject: [PATCH 3/4] Update 127.md --- graph-bfs-dns/127.md | 114 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 110 insertions(+), 4 deletions(-) diff --git a/graph-bfs-dns/127.md b/graph-bfs-dns/127.md index 227c43f..73d7166 100644 --- a/graph-bfs-dns/127.md +++ b/graph-bfs-dns/127.md @@ -1,6 +1,112 @@ -- 問題: []() -- コメント集: [](https://docs.google.com/document/d/11HV35ADPo9QxJOpJQ24FcZvtvioli770WWdZZDaLOfg/mobilebasic#h.o0jquy48e6cy) +- 問題: [127. Word Ladder](https://leetcode.com/problems/word-ladder/description/) +- コメント集: [127. Word Ladder](https://docs.google.com/document/d/11HV35ADPo9QxJOpJQ24FcZvtvioli770WWdZZDaLOfg/mobilebasic#h.o0jquy48e6cy) + - [何かをしようとして、そのことを覚えておきながら別のことをしようとすると、覚えておかないといけないので混乱する](https://discord.com/channels/1084280443945353267/1233603535862628432/1290337478527422528) + - [名前空間](https://discord.com/channels/1084280443945353267/1201211204547383386/1215702126945112094) + - もう少し別関数に切り出した方がいい気もするし、25行程度に収まっているのでしない気もする + - [この問題、結構制限が適当に決められているという印象があります。...](https://discord.com/channels/1084280443945353267/1307605446538039337/1335074776338792512) + - 「どういうものが動かないかが分かったあとに、回避策がいくつかでてくるようにしておく事自体は大切」 --> その通りだと思った + - - 条件 + - 1 <= beginWord.length <= 10 + - endWord.length == beginWord.length + - 1 <= wordList.length <= 5000 + - wordList[i].length == beginWord.length + - beginWord, endWord, and wordList[i] consist of lowercase English letters. + - beginWord != endWord + - All the words in wordList are unique. - 方針1 -- 時間計算量: -- 空間計算量: + - 最短経路問題なのでBFSを使う + - beginword を一文字ずつアルファベット入れ替えて、合致するものが wordList にあればQueueにつめる + - 詰めたものを取り出してまた一文字ずつ入れ替える + - endword に合致したらその時点での深さ+1を返却する +- 時間計算量: O(N * word.length * 26) +- 空間計算量: O(N) + +## BFS +```java +class Solution { + + public int ladderLength(String beginWord, String endWord, List wordList) { + if (!wordList.contains(endWord)) { + return 0; + } + + Queue queue = new ArrayDeque<>(); + queue.add(new MiddleWordAndDepth(beginWord, 1)); + + while (!queue.isEmpty()) { + MiddleWordAndDepth middle = queue.poll(); + String middleWord = middle.middleWord; + int depth = middle.depth; + + for (int i = 0; i < middleWord.length(); i++) { + for (char c = 'a'; c <= 'z'; c++) { + String newWord = middleWord.substring(0, i) + c + middleWord.substring(i + 1); + + if (newWord.equals(endWord)) { + return depth + 1; + } + + if (wordList.contains(newWord)) { + queue.add(new MiddleWordAndDepth(newWord, depth + 1)); + } + } + } + } + + return 0; + } + + record MiddleWordAndDepth(String middleWord, int depth) {} +} +``` + +## BFS 2回目 +- 訪問済み管理を忘れたので無限ループで落ちた, hot がQueueに積まれ続けて無限ループ + ```shell + beginWord = "hot" + endWord = "dog" + wordList = ["hot","dog"] + ``` + +```java +class Solution { + + public int ladderLength(String beginWord, String endWord, List wordList) { + Set wordSet = new HashSet<>(wordList); + + if (!wordSet.contains(endWord)) { + return 0; + } + + Queue queue = new ArrayDeque<>(); + queue.add(new MiddleWordAndDepth(beginWord, 1)); + wordSet.remove(beginWord); + + while (!queue.isEmpty()) { + MiddleWordAndDepth middle = queue.poll(); + String middleWord = middle.middleWord; + int depth = middle.depth; + + for (int i = 0; i < middleWord.length(); i++) { + for (char c = 'a'; c <= 'z'; c++) { + String newWord = middleWord.substring(0, i) + c + middleWord.substring(i + 1); + + if (newWord.equals(endWord)) { + return depth + 1; + } + + if (wordSet.contains(newWord)) { + wordSet.remove(newWord); + queue.add(new MiddleWordAndDepth(newWord, depth + 1)); + } + } + } + } + + return 0; + } + + record MiddleWordAndDepth(String middleWord, int depth) {} +} +``` \ No newline at end of file From 215a76112ca81e1197d35069a451de8009d99648 Mon Sep 17 00:00:00 2001 From: busker <165013324+hiroki-horiguchi-dev@users.noreply.github.com> Date: Sun, 24 May 2026 13:39:57 +0900 Subject: [PATCH 4/4] Revert "Update 127.md" This reverts commit 947fb515d0867964927a60cd761d9bf51385557f. --- graph-bfs-dns/127.md | 114 ++----------------------------------------- 1 file changed, 4 insertions(+), 110 deletions(-) diff --git a/graph-bfs-dns/127.md b/graph-bfs-dns/127.md index 73d7166..227c43f 100644 --- a/graph-bfs-dns/127.md +++ b/graph-bfs-dns/127.md @@ -1,112 +1,6 @@ -- 問題: [127. Word Ladder](https://leetcode.com/problems/word-ladder/description/) -- コメント集: [127. Word Ladder](https://docs.google.com/document/d/11HV35ADPo9QxJOpJQ24FcZvtvioli770WWdZZDaLOfg/mobilebasic#h.o0jquy48e6cy) - - [何かをしようとして、そのことを覚えておきながら別のことをしようとすると、覚えておかないといけないので混乱する](https://discord.com/channels/1084280443945353267/1233603535862628432/1290337478527422528) - - [名前空間](https://discord.com/channels/1084280443945353267/1201211204547383386/1215702126945112094) - - もう少し別関数に切り出した方がいい気もするし、25行程度に収まっているのでしない気もする - - [この問題、結構制限が適当に決められているという印象があります。...](https://discord.com/channels/1084280443945353267/1307605446538039337/1335074776338792512) - - 「どういうものが動かないかが分かったあとに、回避策がいくつかでてくるようにしておく事自体は大切」 --> その通りだと思った - - +- 問題: []() +- コメント集: [](https://docs.google.com/document/d/11HV35ADPo9QxJOpJQ24FcZvtvioli770WWdZZDaLOfg/mobilebasic#h.o0jquy48e6cy) - 条件 - - 1 <= beginWord.length <= 10 - - endWord.length == beginWord.length - - 1 <= wordList.length <= 5000 - - wordList[i].length == beginWord.length - - beginWord, endWord, and wordList[i] consist of lowercase English letters. - - beginWord != endWord - - All the words in wordList are unique. - 方針1 - - 最短経路問題なのでBFSを使う - - beginword を一文字ずつアルファベット入れ替えて、合致するものが wordList にあればQueueにつめる - - 詰めたものを取り出してまた一文字ずつ入れ替える - - endword に合致したらその時点での深さ+1を返却する -- 時間計算量: O(N * word.length * 26) -- 空間計算量: O(N) - -## BFS -```java -class Solution { - - public int ladderLength(String beginWord, String endWord, List wordList) { - if (!wordList.contains(endWord)) { - return 0; - } - - Queue queue = new ArrayDeque<>(); - queue.add(new MiddleWordAndDepth(beginWord, 1)); - - while (!queue.isEmpty()) { - MiddleWordAndDepth middle = queue.poll(); - String middleWord = middle.middleWord; - int depth = middle.depth; - - for (int i = 0; i < middleWord.length(); i++) { - for (char c = 'a'; c <= 'z'; c++) { - String newWord = middleWord.substring(0, i) + c + middleWord.substring(i + 1); - - if (newWord.equals(endWord)) { - return depth + 1; - } - - if (wordList.contains(newWord)) { - queue.add(new MiddleWordAndDepth(newWord, depth + 1)); - } - } - } - } - - return 0; - } - - record MiddleWordAndDepth(String middleWord, int depth) {} -} -``` - -## BFS 2回目 -- 訪問済み管理を忘れたので無限ループで落ちた, hot がQueueに積まれ続けて無限ループ - ```shell - beginWord = "hot" - endWord = "dog" - wordList = ["hot","dog"] - ``` - -```java -class Solution { - - public int ladderLength(String beginWord, String endWord, List wordList) { - Set wordSet = new HashSet<>(wordList); - - if (!wordSet.contains(endWord)) { - return 0; - } - - Queue queue = new ArrayDeque<>(); - queue.add(new MiddleWordAndDepth(beginWord, 1)); - wordSet.remove(beginWord); - - while (!queue.isEmpty()) { - MiddleWordAndDepth middle = queue.poll(); - String middleWord = middle.middleWord; - int depth = middle.depth; - - for (int i = 0; i < middleWord.length(); i++) { - for (char c = 'a'; c <= 'z'; c++) { - String newWord = middleWord.substring(0, i) + c + middleWord.substring(i + 1); - - if (newWord.equals(endWord)) { - return depth + 1; - } - - if (wordSet.contains(newWord)) { - wordSet.remove(newWord); - queue.add(new MiddleWordAndDepth(newWord, depth + 1)); - } - } - } - } - - return 0; - } - - record MiddleWordAndDepth(String middleWord, int depth) {} -} -``` \ No newline at end of file +- 時間計算量: +- 空間計算量: