From e6f2ce4241d0ec0d2ddfc30049622e0cb7c07b5e Mon Sep 17 00:00:00 2001 From: Keisuke KUDO <151166401+Apo-Matchbox@users.noreply.github.com> Date: Fri, 5 Dec 2025 11:28:32 +0900 Subject: [PATCH 1/2] Create 387. First Unique Character in a String --- ...387. First Unique Character in a String.md | 116 ++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 387/387. First Unique Character in a String.md diff --git a/387/387. First Unique Character in a String.md b/387/387. First Unique Character in a String.md new file mode 100644 index 0000000..5f11320 --- /dev/null +++ b/387/387. First Unique Character in a String.md @@ -0,0 +1,116 @@ +# [387. First Unique Character in a String](https://leetcode.com/problems/first-unique-character-in-a-string/description/) +## Step1 + +### 問題意図の考察 +- 問題文の確認 + 1. 文字列sが与えられ、繰り返し使用されていない初めの文字があれば、そのindexを返す + 2. 存在しなければ、-1を返す + +- 制約の確認 + 1. 1<= s.length <= 10^5 (100,000) + 2. sは、lowercase English lettersのみ 26文字 + +### 解法を考える。 + - 初めの文字を保持して、それぞれの文字と付き合わせをする方法だと全文字の検索・線形探索 O(n^2) 10^10 + - 他の方法が思いつかないので、一度これで書く + +初回の回答 +```cpp +#include +#include + +class Solution { +public: + int firstUniqChar(const std::string& s) { + for (int i = 0; i < s.size(); ++i) { + bool unique = true; + for (int j = 0; j < s.size(); ++j) { + if (i != j && s[i] == s[j]) { + unique = false; + break; + } + } + if (unique) { + return i; + } + } + return -1; + } +}; + +``` + +## Step2 +- 調べると、2回スキャンして頻度の集計を行う方法がある。1回目:頻度の集計 2回目:最初にfrequency == 1のindexを返す方法 +- mapだと、O(log n)かかる。全体では、O(n log n) + +```cpp +#include +#include + +class Solution { +public: + int firstUniqChar(const std::string& s) { + std::map character_to_frequency; + for (char c : s) { + character_to_frequency[c]++; + } + for (int i = 0; i < s.size(); ++i) { + if (character_to_frequency[s[i]] == 1) { + return i; + } + } + return -1; + } +}; + +``` + + - この問題では、制約が26文字なので、vectorでも十分 + - ASCII全体やユニコードの扱い、キーの数が大きくなる時、mapが適切か + - vector allocator + * https://en.cppreference.com/w/cpp/container/vector/vector + - ASCII chart + * https://en.cppreference.com/w/cpp/language/ascii.html + * 大文字 -> 小文字の変換などやったのを思い出した。Printableの判定など一通り時間をとって復習したい。 + +```cpp +#include +#include + +class Solution { +public: + int firstUniqChar(const std::string& s) { + std::vector frequency(26, 0); + for (char c : s) { + frequency[c - 'a']++; + } + for (int i = 0; i < static_cast(s.size()); ++i) { + if (frequency[s[i] - 'a'] == 1) { + return i; + } + } + return -1; + } +}; + +``` + +- 他の方のコードを読む + * https://github.com/ryosuketc/leetcode_arai60/pull/15/commits/ef49af137afb1668a68c0910c6bf69f295fe8d79 + * https://github.com/irohafternoon/LeetCode/pull/17/commits/5c32a510c26e07bfd7bd6d0de124fc4ad0f4c95b + * https://github.com/Hurukawa2121/leetcode/pull/15/commits/282ac89bf465b718c26c24ffe60bf799b4fc4b18 + * https://github.com/kt-from-j/leetcode/pull/12/commits/d3fbd5ba09f088c358e78fecbcd8ab468cd0596e + +- 他の解法 + +### データ構造とアルゴリズム + - sは、英小文字のみ('a'~'z'), 26種類なので、vector frequency(26) + - 1回目のループO(n), 2回目のループO(n) で合計 O(n) + +## Step3 + +1. 4min +2. 3min +3. 3min +4. 1min From 141415478dfeca52d62f3c2a97d47514e771ae5c Mon Sep 17 00:00:00 2001 From: Keisuke KUDO <151166401+Apo-Matchbox@users.noreply.github.com> Date: Sat, 6 Dec 2025 07:46:42 +0900 Subject: [PATCH 2/2] Update 387/387. First Unique Character in a String.md Co-authored-by: t9a-dev --- 387/387. First Unique Character in a String.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/387/387. First Unique Character in a String.md b/387/387. First Unique Character in a String.md index 5f11320..a6a8fc4 100644 --- a/387/387. First Unique Character in a String.md +++ b/387/387. First Unique Character in a String.md @@ -81,7 +81,7 @@ public: class Solution { public: int firstUniqChar(const std::string& s) { - std::vector frequency(26, 0); + std::array frequency{}; for (char c : s) { frequency[c - 'a']++; }