Skip to content

387.first unique character in a string#15

Open
nicah4o wants to merge 1 commit into
mainfrom
387.first-unique-character-in-a-string
Open

387.first unique character in a string#15
nicah4o wants to merge 1 commit into
mainfrom
387.first-unique-character-in-a-string

Conversation

@nicah4o
Copy link
Copy Markdown
Owner

@nicah4o nicah4o commented May 17, 2026

}
}
int min_index = INT_MAX;
for (const auto& [key, val] : char_to_index) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

key, valではなく、中身を表す変数名をつけると良いと思います。

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.

普通にchar,indexで良かったですね。
gemini見つつここは書いたのであまり気が遣えていませんでした。

public:
int firstUniqChar(string s) {
unordered_map<char, int> char_to_index;
unordered_set<char> overraps;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

overlapですかね。この問題での重複を表す単語としては不自然な気がしました。

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.

普通にduplicatesとseenなどでよかったですね。

unordered_setですでに現れた文字を記録することを考えたが、返り値インデックスの要求に対してその情報を保持できない。

よくよく考えるとstring型には元々find()メソッドがあることを思い出した。昨日の問題で重厚なcpp版split関数を書いていた方のコードから学んだことだ。
じゃあそもそもhashtableを使う必要すらない。後ろからの探索と前からの探索がぶつかればそれが単独だから、そのインデックスを返せばよい。
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

コードを書く前に計算量を考えているのかが気になりました。

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.

レビューありがとうございます。
この場合、空間計算量を考えてアイデアに飛びついてしまったような形です。
時間計算量はあまり考えられていません。

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

計算量という概念がまだしっくりきていないですかね?

if (!char_to_index.contains(s[i])) {
char_to_index[s[i]] = i;
} else {
char_to_index.erase(s[i]);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

重複を表す特殊な値をchar_to_indexに入れておくと、overrapsをなくせそうですかね。

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.

なるほど、-1などを入れておくということですね。
思いつきませんでした。ありがとうございます。

}
}
int min_index = INT_MAX;
for (const auto& [key, val] : char_to_index) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

こちらのコメントをご参照ください。
hemispherium/LeetCode_Arai60#10 (comment)

overraps.insert(s[i]);
}
}
int min_index = INT_MAX;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

C++11 以降であれば、 std::numeric_limits::max() を使用したほうがモダンに感じます。


// 2. 高速検索のためのハッシュマップ
// 【ポイント】値の代わりに、リスト内の「住所(イテレータ)」を記憶する!
std::unordered_map<std::string, std::list<std::pair<std::string, int>>::iterator> hash_map;
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_map がハッシュマップで実装されるかどうかは、 C++ の規格では決まっていません。 C++ の規格では、時間計算量のみが規定されています。
https://timsong-cpp.github.io/cppwp/n4950/unord.map
一方、ほとんどの実装ではハッシュテーブルが使われると思います。

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.

レビューありがとうございます。
てっきりハッシュマップ=unordered_set, unordered_mapだと思っていました。
他の方のRPでもハッシュマップと書く方が少なかったように感じます。
勉強になりました。


// 2. 高速検索のためのハッシュマップ
// 【ポイント】値の代わりに、リスト内の「住所(イテレータ)」を記憶する!
std::unordered_map<std::string, std::list<std::pair<std::string, int>>::iterator> hash_map;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

変数名に型名を入れても、読み手にとってあまり情報が増えないように思います。キーと値にそれぞれどのようなものが含まれているかが分かる名前が良いと思います。ただ、今回は値にリストへのイテレーターが入るため、難しい所です。 key_to_list_iterator あたりでしょうか。

// データの挿入 (put)
void put(const std::string& key, int value) {
// すでに同じキーがある場合は、古い住所のデータをリストから消す(重複防止)
if (hash_map.find(key) != hash_map.end()) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

if (hash_map.contains(key)) {

のほうがシンプルだと思いました。

あるいは処理の重複を避けるため、イテレーターを使いまわす書き方も良いと思いました。

auto it = hash_map.find(key);
if (it != hash_map.end()) {
    order_list.erase(it);
}

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.

ありがとうございます。
containsの方がわかりやすく簡潔ですね。
なるほど、イテレータを使いまわさない場合、ハッシュ関数を再度呼び出すことになりますね。

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.

4 participants