From 67f051bdc0384cd5afea47037e8c2a274156d7b0 Mon Sep 17 00:00:00 2001 From: kazukiii Date: Wed, 19 Jun 2024 14:55:38 -0700 Subject: [PATCH 1/3] =?UTF-8?q?step1,=20step2,=20step3=E3=82=92=E8=BF=BD?= =?UTF-8?q?=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../README.md | 40 +++++++++++++++++++ .../step1.cpp | 28 +++++++++++++ .../step2.cpp | 14 +++++++ .../step3.cpp | 13 ++++++ 4 files changed, 95 insertions(+) create mode 100644 arai60/first-unique-character-in-a-string/README.md create mode 100644 arai60/first-unique-character-in-a-string/step1.cpp create mode 100644 arai60/first-unique-character-in-a-string/step2.cpp create mode 100644 arai60/first-unique-character-in-a-string/step3.cpp diff --git a/arai60/first-unique-character-in-a-string/README.md b/arai60/first-unique-character-in-a-string/README.md new file mode 100644 index 0000000..24b535f --- /dev/null +++ b/arai60/first-unique-character-in-a-string/README.md @@ -0,0 +1,40 @@ +## 考察 +- 過去に解いたことあり(覚えていない) +- 方針 + - ソートして見ていく + - ソートすることにより同じ文字は隣合う + - 元のインデックスを保持しておく必要あり + - time: O(n lon n), space: O(n log n) -> time, spaceともにソートの分 + - 度数分布を取得してループ + - これも元のインデックスを保持する必要ありそう + - もしかしたらC++のunordered_mapは挿入順を保持する? + - わからないのでドキュメント確認する必要 + - さくっと調べたが特にそのような記載は見当たらなかった + - https://en.cppreference.com/w/cpp/container/unordered_map + - time: O(n), space: O(n) +- 下の方針で行く +- あとは実装 + +## Step1 +- 上で考えたアルゴリズムを実装 +- time: O(n), space: O(n) + +## Step2 +- 他の人のPRを検索 +- Javaには順序のあるHashMapがあるらしい、平衡木を使う方法もある + - Ref. https://github.com/Ryotaro25/leetcode_first60/pull/16/files#r1642839594 + +- Pythonのdictは挿入順序を保持するみたい + - Ref. https://github.com/nittoco/leetcode/pull/20/files#diff-c6374213bbbe17c2850ccd0bfb422c1f5bf40576b93320647cbfd9e9e3724c74R48 + +- 文字列を2回走査すれば、インデックスを保持する必要はなかった + - これは思いつかなかった + - 時間的にも十分だし、一番シンプル + - https://github.com/nittoco/leetcode/pull/20/files#diff-c6374213bbbe17c2850ccd0bfb422c1f5bf40576b93320647cbfd9e9e3724c74R119 + +- 上記を考慮して、C++なら文字列を2回走査するのが一番シンプルだと思ったので修正 + +## Step3 +- 1回目: 55s +- 2回目: 50s +- 3回目: 50s diff --git a/arai60/first-unique-character-in-a-string/step1.cpp b/arai60/first-unique-character-in-a-string/step1.cpp new file mode 100644 index 0000000..458e255 --- /dev/null +++ b/arai60/first-unique-character-in-a-string/step1.cpp @@ -0,0 +1,28 @@ +class Solution { +public: + int firstUniqChar(string s) { + unordered_map char_to_count; + for (int i = 0; i < s.size(); ++i) { + char_to_count[s[i]].count++; + char_to_count[s[i]].index = i; + } + + int answer = INT_MAX; + for (const auto& [num, count]: char_to_count) { + if (count.count == 1) { + answer = min(answer, count.index); + } + } + + if (answer == INT_MAX) { + return -1; + } + return answer; + } + +private: + struct Count { + int count; + int index; + }; +}; diff --git a/arai60/first-unique-character-in-a-string/step2.cpp b/arai60/first-unique-character-in-a-string/step2.cpp new file mode 100644 index 0000000..ab6d63e --- /dev/null +++ b/arai60/first-unique-character-in-a-string/step2.cpp @@ -0,0 +1,14 @@ +class Solution { +public: + int firstUniqChar(string s) { + unordered_map char_to_count; + for (int i = 0; i < s.size(); i++) { + char_to_count[s[i]]++; + } + + for (int i = 0; i < s.size(); i++) { + if (char_to_count[s[i]] == 1) return i; + } + return -1; + } +}; diff --git a/arai60/first-unique-character-in-a-string/step3.cpp b/arai60/first-unique-character-in-a-string/step3.cpp new file mode 100644 index 0000000..db9dd67 --- /dev/null +++ b/arai60/first-unique-character-in-a-string/step3.cpp @@ -0,0 +1,13 @@ +class Solution { +public: + int firstUniqChar(string s) { + unordered_map char_to_count; + for (int i = 0; i < s.size(); i++) { + char_to_count[s[i]]++; + } + for (int i = 0; i < s.size(); i++) { + if (char_to_count[s[i]] == 1) return i; + } + return -1; + } +}; From 3f9bd394a3fa412f471df97ad049ecc89585838d Mon Sep 17 00:00:00 2001 From: kazukiii Date: Wed, 19 Jun 2024 15:07:05 -0700 Subject: [PATCH 2/3] =?UTF-8?q?=E4=B8=80=E9=83=A8=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- arai60/first-unique-character-in-a-string/step1.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arai60/first-unique-character-in-a-string/step1.cpp b/arai60/first-unique-character-in-a-string/step1.cpp index 458e255..16fe54a 100644 --- a/arai60/first-unique-character-in-a-string/step1.cpp +++ b/arai60/first-unique-character-in-a-string/step1.cpp @@ -8,7 +8,7 @@ class Solution { } int answer = INT_MAX; - for (const auto& [num, count]: char_to_count) { + for (const auto& [character, count]: char_to_count) { if (count.count == 1) { answer = min(answer, count.index); } From 50a8420b20079c9f142fcf726015a93ace84764d Mon Sep 17 00:00:00 2001 From: kazukiii Date: Fri, 21 Jun 2024 00:08:07 -0700 Subject: [PATCH 3/3] =?UTF-8?q?step4=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../README.md | 5 +++ .../step4_balanced_bst.cpp | 17 ++++++++++ .../step4_sorting.cpp | 33 +++++++++++++++++++ 3 files changed, 55 insertions(+) create mode 100644 arai60/first-unique-character-in-a-string/step4_balanced_bst.cpp create mode 100644 arai60/first-unique-character-in-a-string/step4_sorting.cpp diff --git a/arai60/first-unique-character-in-a-string/README.md b/arai60/first-unique-character-in-a-string/README.md index 24b535f..0942a03 100644 --- a/arai60/first-unique-character-in-a-string/README.md +++ b/arai60/first-unique-character-in-a-string/README.md @@ -38,3 +38,8 @@ - 1回目: 55s - 2回目: 50s - 3回目: 50s + +## Step4 +- 平衡木とソートを使った実装を追加した + - `step4_balanced_bst.cpp` + - `step4_sorting.cpp` diff --git a/arai60/first-unique-character-in-a-string/step4_balanced_bst.cpp b/arai60/first-unique-character-in-a-string/step4_balanced_bst.cpp new file mode 100644 index 0000000..35694a6 --- /dev/null +++ b/arai60/first-unique-character-in-a-string/step4_balanced_bst.cpp @@ -0,0 +1,17 @@ +class Solution { +public: + int firstUniqChar(string s) { + map first_index_to_char; + unordered_map char_to_first_index; + for (int i = 0; i < s.size(); i++) { + if (char_to_first_index.find(s[i]) != char_to_first_index.end()) { + first_index_to_char.erase(char_to_first_index[s[i]]); + continue; + } + first_index_to_char[i] = s[i]; + char_to_first_index[s[i]] = i; + } + + return !first_index_to_char.empty() ? first_index_to_char.begin()->first : -1; + } +}; diff --git a/arai60/first-unique-character-in-a-string/step4_sorting.cpp b/arai60/first-unique-character-in-a-string/step4_sorting.cpp new file mode 100644 index 0000000..370e296 --- /dev/null +++ b/arai60/first-unique-character-in-a-string/step4_sorting.cpp @@ -0,0 +1,33 @@ +class Solution { +public: + int firstUniqChar(string s) { + vector s_with_index; + for (int i = 0; i < s.size(); i++) { + s_with_index.push_back({s[i], i}); + } + sort(s_with_index.begin(), s_with_index.end(), [](const Character& a, const Character& b) { + return a.character < b.character; + }); + + int count = 1; + int answer = numeric_limits::max(); + for (int i = 0; i < s_with_index.size(); i++) { + if (i < s_with_index.size() - 1 && s_with_index[i].character == s_with_index[i + 1].character) { + count++; + continue; + } + if (count == 1) { + answer = min(answer, s_with_index[i].index); + } + count = 1; + } + + return answer != numeric_limits::max() ? answer : -1; + } + +private: + struct Character { + char character; + int index; + }; +};