diff --git a/929/929. Unique Email Addresses.md b/929/929. Unique Email Addresses.md new file mode 100644 index 0000000..9757e07 --- /dev/null +++ b/929/929. Unique Email Addresses.md @@ -0,0 +1,121 @@ +# [929. Unique Email Addresses](https://leetcode.com/problems/unique-email-addresses/description/) +## Step1 +### 問題意図の考察 + +- 問題文の確認 + 1. メールアドレスは「ローカル名」と「ドメイン名」で構成され、'@'で区切られている + 2. 「ローカル名」の'.'は無視される + 3. 「ローカル名」の'+'以降は無視される + 4. 文字列配列 emailsが与えられ、各emails[i]に1通のメールを送る + 5. 実際に届くメールアドレスがいくつかるか返す + +- 仕様に沿って、文字列を変換する練習 +- メールアドレスを本来届く形に正規化する +- 同じ宛先かどうかの判定(重複なし) + +- 制約の確認 + 1. 1 <= emails.length <= 100, 1 <= emails[i].length <= 100 + * 文字列処理とsetの使い方にfocusか + 2. emails[i]はlowercase letterと'+','.','@'を含む。ASCIIのみ + 3. local@domain @で区切る + 4. 「ローカル名」は+で始まらない + 5. 「ドメイン名」は.comで終わる。.comの前に1文字以上必要 + +### 解法を考える。 +- 実際にメールが届く正規化されたメールアドレスを作って、重複なしで数える +- '@'で区切り、それぞれlocal名とdomain名 +- 以前maekenさんのPRにコメントした時に解法を教えてもらったものを使って書いてみようと思ったが忘れていた。 + +初回の回答 *maekenさんの回答を参照 + +```cpp +#include +#include +#include + +class Solution { + public: + int numUniqueEmails(const std::vector& emails) { + std::set seen; + + for (const std::string& email : emails) { + seen.insert(NormalizeEmail(email)); + } + + return static_cast(seen.size()); + } + + private: + std::string NormalizeEmail(const std::string& email) const { + std::size_t at_position = email.find('@'); + std::string local = email.substr(0, at_position); + std::string domain = email.substr(at_position); + + std::size_t plus_position = local.find('+'); + if (plus_position != std::string::npos) { + local.resize(plus_position); + } + + std::erase(local, '.'); + + return local + domain; + } +}; + +``` + +## Step2 + +- at_positionはatでも分かりそう +- UpperCamelCase +- std::moveは、まだ理解できないところがあったので、一旦避けた。 + * https://discord.com/channels/1084280443945353267/1237649827240742942/1359594009168973844 +- std::erase + * https://en.cppreference.com/w/cpp/string/basic_string/erase2.html?utm_source=chatgpt.com + +```cpp +#include +#include +#include + +class Solution { + public: + int numUniqueEmails(const std::vector& emails) { + std::set unique_emails; + + for (const std::string& email : emails) { + unique_emails.insert(Normalize(email)); + } + + return static_cast(unique_emails.size()); + } + + private: + std::string Normalize(const std::string& email) const { + std::size_t at = email.find('@'); + std::string local = email.substr(0, at); + std::string domain = email.substr(at); + + std::size_t plus = local.find('+'); + if (plus != std::string::npos) local.resize(plus); + + std::erase(local, '.'); + + return local + domain; + } +}; + +``` +### 参照Github +- https://github.com/irohafternoon/LeetCode/pull/16/commits/9efdb742221858a6031b76e20726cce3fe51ab87 +- https://github.com/nktr-cp/leetcode/pull/15/commits/01efb11f60afdafae430a8f15cf8f1681a7e8f4c#diff-bae31ba78234fa64f5611b46638c8ab12100cbf3d087c01edeb040136e1a04ee +- https://github.com/maeken4/Arai60/pull/13/commits/66b5137856e054e0a2addac1fddb6644cf47eec9#diff-f199a2e7d3a798077b760cce25b9ff7619abec7cb630b018aa781277ea233fb6 + +### データ構造とアルゴリズム + +## Step3 *自然な流れ(感覚に落とし込む) +1. 8min +2. 9min +3. 6min +4. 7min +5. 6min