Skip to content

Create GroupAnagrams.md#9

Open
kt-from-j wants to merge 1 commit intomainfrom
GroupAnagrams
Open

Create GroupAnagrams.md#9
kt-from-j wants to merge 1 commit intomainfrom
GroupAnagrams

Conversation

@kt-from-j
Copy link
Owner

今回解いた問題:
49. Group Anagrams
次に解く問題:
349. Intersection of Two Arrays

Copy link

@nanae772 nanae772 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

全体的に読みやすく、特に違和感もありませんでした。

Comment on lines +58 to +61
StringBuilder sb = new StringBuilder();
for (int count : alphabetCount) {
sb.append("#").append(count);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Javaのことはあまり詳しくなく恐縮ですが、ここは[1,2,3]のような配列はmutableだからkeyにできないので、immutableな1#2#3という文字列に変換しているという理解でよいでしょうか?

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

配列をkeyにすることは可能なのですが、配列の参照(アドレス)を元にhashを計算するので同一のObjectじゃないと同じような形をした配列でもMapから値を取り出せません。
以下のイメージです。

Map<int[], String> map = new HashMap<>();
int[] key1 = {1, 2};
int[] key2 = {1, 2};

map.put(key1, "hello");
System.out.println(map.get(key1)); // hello
System.out.println(map.get(key2)); // null

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

class Solution {
    public List<List<String>> groupAnagrams(String[] strs) {
        HashMap<List<Integer>, List<String>> anagramKeyToAnagrams = new HashMap();
        for (String str : strs) {
            List<Integer> anagramKey = genAnagramKey(str);
            anagramKeyToAnagrams
                    // 新規登録の場合は初期値として空の配列を登録
                    .computeIfAbsent(anagramKey, (key) -> new ArrayList<>())
                    .add(str);
        }
        return new ArrayList<>(anagramKeyToAnagrams.values());
    }

    private List<Integer> genAnagramKey(String unsorted) {
        char[] chars = unsorted.toCharArray();
        List<Integer> alphabetCount = new ArrayList<>();
        for (char c: chars) {
            //「-'a'」すると
            // a → 0, b → 1, z → 26という具合になる
            int index = c - 'a';
            while (alphabetCount.size() <= index) {
                alphabetCount.add(0);
            }
            alphabetCount.set(index, alphabetCount.get(index) + 1);
        }
        return alphabetCount;
    }
}

軽くJavaの実装を見たのですが、ArrayListだとハッシュ値の計算を要素から計算しているのでオブジェクトが異なってもhash値が一致するので上のコードだと動きますね。

https://github.com/openjdk/jdk/blob/182fbc2b836d27410ccd0da512acb17bac9363c1/src/java.base/share/classes/java/util/ArrayList.java#L670-L681

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ArrayListのハッシュ計算について意識したことがなかったです。
実装確認しました。確かにこれでも意図した動作をしますね。
ありがとうございます!

private String genAnagramKey(String unsorted) {
char[] chars = unsorted.toCharArray();
int[] alphabetCount = new int[26];
for (char c: chars) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

細かいのですが、for (char c : chars) でしょうか(:の左にスペース)。

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

見落としてました、ありがとうございます!

# step3 3回ミスなく書く

## 解答
- step1と同様の実装

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

全体的に読みやすいなと感じました。

return new ArrayList<>(anagramKeyToAnagrams.values());
}

private String genAnagramKey(String unsorted) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

generateの意味だと思いますが、genがどこまで一般的なのか自分はわからないのと、書く回数が多くないのでgenerateにすると思います。

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

親しんだ環境では一般的だったので、半ば無意識でした。
ご指摘ありがとうございます!

Comment on lines +58 to +61
StringBuilder sb = new StringBuilder();
for (int count : alphabetCount) {
sb.append("#").append(count);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

class Solution {
    public List<List<String>> groupAnagrams(String[] strs) {
        HashMap<List<Integer>, List<String>> anagramKeyToAnagrams = new HashMap();
        for (String str : strs) {
            List<Integer> anagramKey = genAnagramKey(str);
            anagramKeyToAnagrams
                    // 新規登録の場合は初期値として空の配列を登録
                    .computeIfAbsent(anagramKey, (key) -> new ArrayList<>())
                    .add(str);
        }
        return new ArrayList<>(anagramKeyToAnagrams.values());
    }

    private List<Integer> genAnagramKey(String unsorted) {
        char[] chars = unsorted.toCharArray();
        List<Integer> alphabetCount = new ArrayList<>();
        for (char c: chars) {
            //「-'a'」すると
            // a → 0, b → 1, z → 26という具合になる
            int index = c - 'a';
            while (alphabetCount.size() <= index) {
                alphabetCount.add(0);
            }
            alphabetCount.set(index, alphabetCount.get(index) + 1);
        }
        return alphabetCount;
    }
}

軽くJavaの実装を見たのですが、ArrayListだとハッシュ値の計算を要素から計算しているのでオブジェクトが異なってもhash値が一致するので上のコードだと動きますね。

https://github.com/openjdk/jdk/blob/182fbc2b836d27410ccd0da512acb17bac9363c1/src/java.base/share/classes/java/util/ArrayList.java#L670-L681

@5103246
Copy link

5103246 commented Oct 7, 2025

読みやすかったです

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants