Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Copy link
Copy Markdown

@Hiroto-Iizuka Hiroto-Iizuka Jan 18, 2026

Choose a reason for hiding this comment

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

[IMO] コードとは関係ないのですが、ディレクトリ名やファイル名に (スペース)を入れるのは好みではありません。CLIなどでエスケープが必要だったりと実務上の手間が増えるからです。
私はKth_Largest_Element_in_a_Stream/memo.mdみたいな感じで _ を入れてます。

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

返信が遅くなり、大変失礼いたしました。
ファイル名の作法があまりわかっていませんでしたが
いろいろとデメリットがありそうですね。
次からは、スペースは使わず_を使用しようと思います。
レビューいただきありがとうございます。

Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
//STEP1
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

本筋とは関係ないですが、Markdownの記法に従っておくとレンダリングしたときに見やすいです。

Suggested change
//STEP1
## STEP1

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

返信が遅くなり、大変失礼いたしました。
mdファイルがマークダウンという記法で書かれたファイルであること、このコメントで理解しました。
記法を調べて、それにのっとって書くようにします。
レビューいただきありがとうございます。


■手作業でどうやるか?
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

手作業でやってみる、いいですね 👍


例:loveleetcode

l→後ろの文字を一つずつ見ていく。だめ

o→後ろの文字を一つずつ見ていく。だめ

v→後ろの文字を一つずつ見ていく。OK

重複を見つけたらNGの文字一覧に放り込んで行く。

もしNG一覧にあれば、その文字は調べず、次の文字の重複チェックをする。

もしNG一覧になければ、その要素より後を調べる。

NGリストはsetにすればいいかな?



```java
class Solution {
public int firstUniqChar(String s) {
Set<Character> repeating = new HashSet<>();
int n = s.length();
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

nは定義せずに済ませても良いのではないかと思いました(好みの範囲かもしれません)

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

返信遅くなり、大変失礼いたしました。
ここは、あまり深く考えずに書いていたのですが、
確かにnの定義はせず、
s.length()そのままでも良さそうですね。
変数定義の必要性を考えた上で書くことに
気をつけたいと思います。
レビューいただきありがとうございます。

for (int i = 0; i < n; i++) {
char c = s.charAt(i);
Comment on lines +26 to +29
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

最初に読んだ際に repeating が何を表しているのかが不明瞭であるように感じました。おそらく repeating と duplicated が、どちらも「重複」という同じ意味だが違う表現になっていることが原因だと思います。

命名としては seen などをよく見るので、repeating の代わりにこちらもご検討ください。

また、duplicated という命名の Set を持ってしまって、if (!duplicated) の部分をフラグではなく、if (!duplicated.contains(c))として、Set で条件分岐を行うのもありかなと思いました。

以下参考まで。

class Solution {
    public int firstUniqChar(String s) {
        Set<Character> duplicated = new HashSet<>();
        int n = s.length();
        for (int i = 0; i < n; i++) {
            char c = s.charAt(i);
            if (duplicated.contains(c)) {
                continue;
            }
            for (int j = i + 1; j < n; j++) {
                if (c == s.charAt(j)) {
                    duplicated.add(c);
                    break;
                }
            }
            if (!duplicated.contains(c)) {
                return i;
            }
        }
        return -1;
    }
}

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

返信が遅くなり、大変失礼いたしました。
確かに、duplicatedとrepeatingは同じような意味なので、コードの意味が取りにくいかもしれません。
フラグを使ってみたくて、duplicatedフラグをやってみたのですが、なくても問題ないですね。
似たような変数名が存在してないかや別の表現でできないか、気を配ろうと思います。
レビューいただきありがとうございます。

if (repeating.contains(c)) {
continue;
}
boolean duplicated = false;
for (int j = i + 1; j < n; j++) {
if (c == s.charAt(j)) {
repeating.add(c);
duplicated = true;
break;
}
}
if (!duplicated) {
return i;
}
}
return -1;
}
}
```

■メモ

初歩的で大変お恥ずかしいですが、

やりたいことは構文的なところの知識が足りなかったので、実装がうまくできず

chatGPTにやりたいことをきれいに実装してもらった後、不明点を調べました。

わからないところ、感想など

・配列のようにインデックスを指定してString中の文字を取得したい

→インデックスを指定してStringのchar値を返すメソッド charAt

https://docs.oracle.com/javase/jp/8/docs/api/java/lang/String.html#charAt-int-

・boolean duplicatedで重複のあるなしを管理しているのは、

自分で考えていた時は思いつかなかったが、見やすくていいなと思った。

・計算量について

時間計算量は、O(N^2) (二重のforループ)

空間計算量は、O(N) (重複文字数に比例してメモリが必要)





//STEP2

■ほかの人の解答を読む

Leetcodeの解答例

```java
class Solution {
public int firstUniqChar(String s) {
int[] c=new int[26];
for(int i=0;i<s.length();i++){
c[s.charAt(i)-'a']++;
}
for(int i=0;i<s.length();i++){
if(c[s.charAt(i)-'a']==1)
return i;
}
return -1;
}
}
```

手作業で表現するなら、

①文字の表を作り、出現回数を記録する。

②文字列の順に表を確認し、最初に出現回数1が出てきたらそこでインデックスを返す。

計算量は以下の通りで、こちらの方が速くて省メモリ。

時間計算量は、O(N) (forループ2回)

空間計算量は、O(1) (26文字分のメモリが必要)



入力の文字列が英小文字26字という前提があるので、

26字分のサイズの配列しか用意しないのは計算量の観点でエコだと思った。

配列のインデックスの計算にc[s.charAt(i)-'a']ができるというのは、初めて知った。

調べたところ、javaでは文字を数字として扱うことができるから、このような書き方ができるということだった。

ただし、もし入力値に英小文字以外が含まれていた場合、エラーとなる。

入力値が英小文字になるよう完全にコントロールできるか、エラーの処理を追加してあげれば、

大量の入力値や、とても長い入力値でも処理が速く、空間計算量も少ないので、効率的に動くと思う。



一方でこちらの解答

https://github.com/kazukiii/leetcode/pull/16/files#diff-ab5f3d992bba7dfdbae5fb89c6211844968879aaa279be404afd515fc3d9229d

同じやり方で処理を行っているが、配列ではなくMapを用いている。

もし英小文字以外が入力値に入ってきた場合にも対応可能。

上記のC++の解答ではunordered_mapを使用しているが、javaではmapは最初からunorderedということなので、今回は気にしなくてよさそう。

https://stackoverflow.com/questions/7792523/hashmap-gives-an-unordered-list-of-values
Comment on lines +140 to +142
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

何を気にしているのか次第ですが、私の場合、この箇所を読んだときに unordered ということは「orderedであることが期待されうるのに、そうでないこと」を明示しているのだな、と感じました。

Javaに詳しくないので調べてみました。

https://developer.android.com/reference/java/util/HashMap

This class makes no guarantees as to the order of the map; in particular, it does not guarantee that the order will remain constant over time.

https://developer.android.com/reference/java/util/LinkedHashMap

This linked list defines the encounter order (the order of iteration), which is normally the order in which keys were inserted into the map (insertion-order). The least recently inserted entry (the eldest) is first, and the youngest entry is last.

HashMap は挿入順に取り出せることを保証しませんが、LinkedHashMap は保証しています。

ちなみに、keyをソートしてくれる TreeMap というのもあるみたいですね。
https://developer.android.com/reference/java/util/TreeMap

Note that the ordering maintained by a tree map, like any sorted map, and whether or not an explicit comparator is provided, must be consistent with equals if this sorted map is to correctly implement the Map interface.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Java は TreeMap と HashMap があって、C++ の map と unordered_map に大まかに対応しています。
この2つの中身がどんな形かは大まかに知っておいていいでしょう。

Copy link
Copy Markdown
Owner Author

@achotto achotto Feb 5, 2026

Choose a reason for hiding this comment

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

mamo3grさん、odaさん
Mapの種類についてコメントやリンクのご提示などありがとうございます。
問題を解くことだけを考えていましたが、
どんな種類があるかを把握したうえで、
適切に選択することができるよう頭に入れたいと思います。
arai60の2週目をやる時になったら、javaではない言語でもやってみたいと思います。




https://github.com/t0hsumi/leetcode/pull/15#discussion_r1930362913

重複がないことの証明として、「左から読んだときと右から読んだときで、添字が変わらない」ことを使う方法があるとのこと。

このやり方もスマートな感じがした。面白そうなので、時間があれば自分で書いてみたい。

今は、一つの問題にずっと取り組むより、いろいろな問題に触れることを優先しようと思うので、とりあえずメモに残す。



//STEP3

Mapのメソッドなどを調べつつSTEP2で見た方法を自分で実装する。

```java
class Solution {
public int firstUniqChar(String s) {
Map<Character, Integer> counter = new HashMap<>();
for (int i = 0; i < s.length(); i++) {
counter.put(s.charAt(i), counter.getOrDefault(s.charAt(i), 0) + 1);
//ここは、counters.merge(s.charAt(i), 1, (oldValue, newValue) -> oldValue + newValue);
//でも同じことが可能。
//ラムダ式というものらしい。
}
for (int i = 0; i < s.length(); i++) {
if (counter.get(s.charAt(i)) == 1) {
return i;
}
}
Comment on lines +170 to +174
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

counter が挿入順に要素 (key-value) を取り出せるなら、s を参照せずに、はじめに1が出てきた時点で返せそうですね。

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

LinkedHashMap というものはあります。
https://docs.oracle.com/javase/jp/8/docs/api/java/util/LinkedHashMap.html

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

LinkedHashMap は、個人的には知らなくてもいいんですが、しかし、面接ではよく聞かれます。

return -1;
}
}
```