diff --git a/solution/0900-0999/0929.Unique Email Addresses/README.md b/solution/0900-0999/0929.Unique Email Addresses/README.md index 4f83de7313ac7..bb309856cd9e5 100644 --- a/solution/0900-0999/0929.Unique Email Addresses/README.md +++ b/solution/0900-0999/0929.Unique Email Addresses/README.md @@ -79,7 +79,11 @@ tags: ### 方法一:哈希表 -利用哈希表存放转换后的电子邮件,最后返回哈希表的 size 即可。 +我们可以用一个哈希表 $s$ 来存储所有的电子邮件地址,然后遍历数组 $\textit{emails}$,对于每个电子邮件地址,我们将其分为本地名和域名两部分,然后对本地名进行处理,去掉所有的点号和加号后面的字符,最后将处理后的本地名和域名拼接起来,加入哈希表 $s$ 中。 + +最后返回哈希表 $s$ 的大小即可。 + +时间复杂度 $O(L)$,空间复杂度 $O(L)$,其中 $L$ 为所有电子邮件地址的长度之和。 @@ -90,11 +94,15 @@ class Solution: def numUniqueEmails(self, emails: List[str]) -> int: s = set() for email in emails: - local, domain = email.split('@') - local = local.replace('.', '') - if (i := local.find('+')) != -1: - local = local[:i] - s.add(local + '@' + domain) + local, domain = email.split("@") + t = [] + for c in local: + if c == ".": + continue + if c == "+": + break + t.append(c) + s.add("".join(t) + "@" + domain) return len(s) ``` @@ -105,14 +113,20 @@ class Solution { public int numUniqueEmails(String[] emails) { Set s = new HashSet<>(); for (String email : emails) { - String[] t = email.split("@"); - String local = t[0].replace(".", ""); - String domain = t[1]; - int i = local.indexOf('+'); - if (i != -1) { - local = local.substring(0, i); + String[] parts = email.split("@"); + String local = parts[0]; + String domain = parts[1]; + StringBuilder t = new StringBuilder(); + for (char c : local.toCharArray()) { + if (c == '.') { + continue; + } + if (c == '+') { + break; + } + t.append(c); } - s.add(local + "@" + domain); + s.add(t.toString() + "@" + domain); } return s.size(); } @@ -126,15 +140,21 @@ class Solution { public: int numUniqueEmails(vector& emails) { unordered_set s; - for (auto& email : emails) { - int i = email.find('@'); - string local = email.substr(0, i); - string domain = email.substr(i + 1); - i = local.find('+', 0); - if (~i) local = local.substr(0, i); - while (~(i = local.find('.', 0))) - local.erase(local.begin() + i); - s.insert(local + "@" + domain); + for (const string& email : emails) { + size_t atPos = email.find('@'); + string local = email.substr(0, atPos); + string domain = email.substr(atPos + 1); + string t; + for (char c : local) { + if (c == '.') { + continue; + } + if (c == '+') { + break; + } + t.push_back(c); + } + s.insert(t + "@" + domain); } return s.size(); } @@ -145,13 +165,22 @@ public: ```go func numUniqueEmails(emails []string) int { - s := map[string]bool{} + s := make(map[string]struct{}) for _, email := range emails { - i := strings.IndexByte(email, '@') - local := strings.SplitN(email[:i], "+", 2)[0] - local = strings.ReplaceAll(local, ".", "") - domain := email[i:] - s[local+domain] = true + parts := strings.Split(email, "@") + local := parts[0] + domain := parts[1] + var t strings.Builder + for _, c := range local { + if c == '.' { + continue + } + if c == '+' { + break + } + t.WriteByte(byte(c)) + } + s[t.String()+"@"+domain] = struct{}{} } return len(s) } @@ -161,11 +190,22 @@ func numUniqueEmails(emails []string) int { ```ts function numUniqueEmails(emails: string[]): number { - return new Set( - emails - .map(email => email.split('@')) - .map(([start, end]) => start.replace(/\+.*|\./g, '') + '@' + end), - ).size; + const s = new Set(); + for (const email of emails) { + const [local, domain] = email.split('@'); + let t = ''; + for (const c of local) { + if (c === '.') { + continue; + } + if (c === '+') { + break; + } + t += c; + } + s.add(t + '@' + domain); + } + return s.size; } ``` @@ -173,26 +213,29 @@ function numUniqueEmails(emails: string[]): number { ```rust use std::collections::HashSet; + impl Solution { pub fn num_unique_emails(emails: Vec) -> i32 { - let mut set = HashSet::new(); - for email in emails.iter() { - let res: Vec<&str> = email.split('@').collect(); - let mut s = String::new(); - for &c in res[0].as_bytes().iter() { - if c == b'.' { + let mut s = HashSet::new(); + + for email in emails { + let parts: Vec<&str> = email.split('@').collect(); + let local = parts[0]; + let domain = parts[1]; + let mut t = String::new(); + for c in local.chars() { + if c == '.' { continue; } - if c == b'+' { + if c == '+' { break; } - s.push(c as char); + t.push(c); } - s.push('@'); - s.push_str(res[1]); - set.insert(s); + s.insert(format!("{}@{}", t, domain)); } - set.len() as i32 + + s.len() as i32 } } ``` @@ -200,45 +243,27 @@ impl Solution { #### JavaScript ```js -const numUniqueEmails2 = function (emails) { - const emailFilter = function (str) { - let index = str.search(/@/); - let s = str.substring(0, index); - let s2 = str.substring(index + 1, str.length); - let res = ''; - for (let i = 0; i < s.length; i++) { - if (s[i] === '+') break; - if (s[i] === '.') continue; - res = res + s[i]; - } - return res + s2; - }; - - let arr = []; - for (let i = 0; i < emails.length; i++) { - let t = emailFilter(emails[i]); - if (arr.indexOf(t) === -1) { - arr.push(t); +/** + * @param {string[]} emails + * @return {number} + */ +var numUniqueEmails = function (emails) { + const s = new Set(); + for (const email of emails) { + const [local, domain] = email.split('@'); + let t = ''; + for (const c of local) { + if (c === '.') { + continue; + } + if (c === '+') { + break; + } + t += c; } + s.add(t + '@' + domain); } - return arr.length; -}; - -const numUniqueEmails = function (emails) { - let arr = emails.map(str => { - let index = str.search(/@/); - let s = str.substring(0, index); - let s2 = str.substring(index + 1, str.length); - let res = ''; - for (let i = 0; i < s.length; i++) { - if (s[i] === '+') break; - if (s[i] === '.') continue; - res = res + s[i]; - } - return res + s2; - }); - let set = new Set(arr); - return set.size; + return s.size; }; ``` diff --git a/solution/0900-0999/0929.Unique Email Addresses/README_EN.md b/solution/0900-0999/0929.Unique Email Addresses/README_EN.md index 3bbea9e8b3ecf..9a330f1d0c4fb 100644 --- a/solution/0900-0999/0929.Unique Email Addresses/README_EN.md +++ b/solution/0900-0999/0929.Unique Email Addresses/README_EN.md @@ -76,7 +76,13 @@ tags: -### Solution 1 +### Solution 1: Hash Table + +We can use a hash table $s$ to store all unique email addresses. Then, we traverse the array $\textit{emails}$. For each email address, we split it into the local part and the domain part. We process the local part by removing all dots and ignoring characters after a plus sign. Finally, we concatenate the processed local part with the domain part and add it to the hash table $s$. + +In the end, we return the size of the hash table $s$. + +The time complexity is $O(L)$, and the space complexity is $O(L)$, where $L$ is the total length of all email addresses. @@ -87,11 +93,15 @@ class Solution: def numUniqueEmails(self, emails: List[str]) -> int: s = set() for email in emails: - local, domain = email.split('@') - local = local.replace('.', '') - if (i := local.find('+')) != -1: - local = local[:i] - s.add(local + '@' + domain) + local, domain = email.split("@") + t = [] + for c in local: + if c == ".": + continue + if c == "+": + break + t.append(c) + s.add("".join(t) + "@" + domain) return len(s) ``` @@ -102,14 +112,20 @@ class Solution { public int numUniqueEmails(String[] emails) { Set s = new HashSet<>(); for (String email : emails) { - String[] t = email.split("@"); - String local = t[0].replace(".", ""); - String domain = t[1]; - int i = local.indexOf('+'); - if (i != -1) { - local = local.substring(0, i); + String[] parts = email.split("@"); + String local = parts[0]; + String domain = parts[1]; + StringBuilder t = new StringBuilder(); + for (char c : local.toCharArray()) { + if (c == '.') { + continue; + } + if (c == '+') { + break; + } + t.append(c); } - s.add(local + "@" + domain); + s.add(t.toString() + "@" + domain); } return s.size(); } @@ -123,15 +139,21 @@ class Solution { public: int numUniqueEmails(vector& emails) { unordered_set s; - for (auto& email : emails) { - int i = email.find('@'); - string local = email.substr(0, i); - string domain = email.substr(i + 1); - i = local.find('+', 0); - if (~i) local = local.substr(0, i); - while (~(i = local.find('.', 0))) - local.erase(local.begin() + i); - s.insert(local + "@" + domain); + for (const string& email : emails) { + size_t atPos = email.find('@'); + string local = email.substr(0, atPos); + string domain = email.substr(atPos + 1); + string t; + for (char c : local) { + if (c == '.') { + continue; + } + if (c == '+') { + break; + } + t.push_back(c); + } + s.insert(t + "@" + domain); } return s.size(); } @@ -142,13 +164,22 @@ public: ```go func numUniqueEmails(emails []string) int { - s := map[string]bool{} + s := make(map[string]struct{}) for _, email := range emails { - i := strings.IndexByte(email, '@') - local := strings.SplitN(email[:i], "+", 2)[0] - local = strings.ReplaceAll(local, ".", "") - domain := email[i:] - s[local+domain] = true + parts := strings.Split(email, "@") + local := parts[0] + domain := parts[1] + var t strings.Builder + for _, c := range local { + if c == '.' { + continue + } + if c == '+' { + break + } + t.WriteByte(byte(c)) + } + s[t.String()+"@"+domain] = struct{}{} } return len(s) } @@ -158,11 +189,22 @@ func numUniqueEmails(emails []string) int { ```ts function numUniqueEmails(emails: string[]): number { - return new Set( - emails - .map(email => email.split('@')) - .map(([start, end]) => start.replace(/\+.*|\./g, '') + '@' + end), - ).size; + const s = new Set(); + for (const email of emails) { + const [local, domain] = email.split('@'); + let t = ''; + for (const c of local) { + if (c === '.') { + continue; + } + if (c === '+') { + break; + } + t += c; + } + s.add(t + '@' + domain); + } + return s.size; } ``` @@ -170,26 +212,29 @@ function numUniqueEmails(emails: string[]): number { ```rust use std::collections::HashSet; + impl Solution { pub fn num_unique_emails(emails: Vec) -> i32 { - let mut set = HashSet::new(); - for email in emails.iter() { - let res: Vec<&str> = email.split('@').collect(); - let mut s = String::new(); - for &c in res[0].as_bytes().iter() { - if c == b'.' { + let mut s = HashSet::new(); + + for email in emails { + let parts: Vec<&str> = email.split('@').collect(); + let local = parts[0]; + let domain = parts[1]; + let mut t = String::new(); + for c in local.chars() { + if c == '.' { continue; } - if c == b'+' { + if c == '+' { break; } - s.push(c as char); + t.push(c); } - s.push('@'); - s.push_str(res[1]); - set.insert(s); + s.insert(format!("{}@{}", t, domain)); } - set.len() as i32 + + s.len() as i32 } } ``` @@ -197,45 +242,27 @@ impl Solution { #### JavaScript ```js -const numUniqueEmails2 = function (emails) { - const emailFilter = function (str) { - let index = str.search(/@/); - let s = str.substring(0, index); - let s2 = str.substring(index + 1, str.length); - let res = ''; - for (let i = 0; i < s.length; i++) { - if (s[i] === '+') break; - if (s[i] === '.') continue; - res = res + s[i]; - } - return res + s2; - }; - - let arr = []; - for (let i = 0; i < emails.length; i++) { - let t = emailFilter(emails[i]); - if (arr.indexOf(t) === -1) { - arr.push(t); +/** + * @param {string[]} emails + * @return {number} + */ +var numUniqueEmails = function (emails) { + const s = new Set(); + for (const email of emails) { + const [local, domain] = email.split('@'); + let t = ''; + for (const c of local) { + if (c === '.') { + continue; + } + if (c === '+') { + break; + } + t += c; } + s.add(t + '@' + domain); } - return arr.length; -}; - -const numUniqueEmails = function (emails) { - let arr = emails.map(str => { - let index = str.search(/@/); - let s = str.substring(0, index); - let s2 = str.substring(index + 1, str.length); - let res = ''; - for (let i = 0; i < s.length; i++) { - if (s[i] === '+') break; - if (s[i] === '.') continue; - res = res + s[i]; - } - return res + s2; - }); - let set = new Set(arr); - return set.size; + return s.size; }; ``` diff --git a/solution/0900-0999/0929.Unique Email Addresses/Solution.cpp b/solution/0900-0999/0929.Unique Email Addresses/Solution.cpp index b4d747dad2a99..733d907903c5a 100644 --- a/solution/0900-0999/0929.Unique Email Addresses/Solution.cpp +++ b/solution/0900-0999/0929.Unique Email Addresses/Solution.cpp @@ -2,16 +2,22 @@ class Solution { public: int numUniqueEmails(vector& emails) { unordered_set s; - for (auto& email : emails) { - int i = email.find('@'); - string local = email.substr(0, i); - string domain = email.substr(i + 1); - i = local.find('+', 0); - if (~i) local = local.substr(0, i); - while (~(i = local.find('.', 0))) - local.erase(local.begin() + i); - s.insert(local + "@" + domain); + for (const string& email : emails) { + size_t atPos = email.find('@'); + string local = email.substr(0, atPos); + string domain = email.substr(atPos + 1); + string t; + for (char c : local) { + if (c == '.') { + continue; + } + if (c == '+') { + break; + } + t.push_back(c); + } + s.insert(t + "@" + domain); } return s.size(); } -}; \ No newline at end of file +}; diff --git a/solution/0900-0999/0929.Unique Email Addresses/Solution.go b/solution/0900-0999/0929.Unique Email Addresses/Solution.go index 574d6ac634d0a..6466f2ec1da0f 100644 --- a/solution/0900-0999/0929.Unique Email Addresses/Solution.go +++ b/solution/0900-0999/0929.Unique Email Addresses/Solution.go @@ -1,11 +1,20 @@ func numUniqueEmails(emails []string) int { - s := map[string]bool{} + s := make(map[string]struct{}) for _, email := range emails { - i := strings.IndexByte(email, '@') - local := strings.SplitN(email[:i], "+", 2)[0] - local = strings.ReplaceAll(local, ".", "") - domain := email[i:] - s[local+domain] = true + parts := strings.Split(email, "@") + local := parts[0] + domain := parts[1] + var t strings.Builder + for _, c := range local { + if c == '.' { + continue + } + if c == '+' { + break + } + t.WriteByte(byte(c)) + } + s[t.String()+"@"+domain] = struct{}{} } return len(s) -} \ No newline at end of file +} diff --git a/solution/0900-0999/0929.Unique Email Addresses/Solution.java b/solution/0900-0999/0929.Unique Email Addresses/Solution.java index 8b8f14b2aa945..e85c263adfee3 100644 --- a/solution/0900-0999/0929.Unique Email Addresses/Solution.java +++ b/solution/0900-0999/0929.Unique Email Addresses/Solution.java @@ -2,15 +2,21 @@ class Solution { public int numUniqueEmails(String[] emails) { Set s = new HashSet<>(); for (String email : emails) { - String[] t = email.split("@"); - String local = t[0].replace(".", ""); - String domain = t[1]; - int i = local.indexOf('+'); - if (i != -1) { - local = local.substring(0, i); + String[] parts = email.split("@"); + String local = parts[0]; + String domain = parts[1]; + StringBuilder t = new StringBuilder(); + for (char c : local.toCharArray()) { + if (c == '.') { + continue; + } + if (c == '+') { + break; + } + t.append(c); } - s.add(local + "@" + domain); + s.add(t.toString() + "@" + domain); } return s.size(); } -} \ No newline at end of file +} diff --git a/solution/0900-0999/0929.Unique Email Addresses/Solution.js b/solution/0900-0999/0929.Unique Email Addresses/Solution.js index 631124018648f..ee01f3985bbca 100644 --- a/solution/0900-0999/0929.Unique Email Addresses/Solution.js +++ b/solution/0900-0999/0929.Unique Email Addresses/Solution.js @@ -1,40 +1,22 @@ -const numUniqueEmails2 = function (emails) { - const emailFilter = function (str) { - let index = str.search(/@/); - let s = str.substring(0, index); - let s2 = str.substring(index + 1, str.length); - let res = ''; - for (let i = 0; i < s.length; i++) { - if (s[i] === '+') break; - if (s[i] === '.') continue; - res = res + s[i]; - } - return res + s2; - }; - - let arr = []; - for (let i = 0; i < emails.length; i++) { - let t = emailFilter(emails[i]); - if (arr.indexOf(t) === -1) { - arr.push(t); +/** + * @param {string[]} emails + * @return {number} + */ +var numUniqueEmails = function (emails) { + const s = new Set(); + for (const email of emails) { + const [local, domain] = email.split('@'); + let t = ''; + for (const c of local) { + if (c === '.') { + continue; + } + if (c === '+') { + break; + } + t += c; } + s.add(t + '@' + domain); } - return arr.length; -}; - -const numUniqueEmails = function (emails) { - let arr = emails.map(str => { - let index = str.search(/@/); - let s = str.substring(0, index); - let s2 = str.substring(index + 1, str.length); - let res = ''; - for (let i = 0; i < s.length; i++) { - if (s[i] === '+') break; - if (s[i] === '.') continue; - res = res + s[i]; - } - return res + s2; - }); - let set = new Set(arr); - return set.size; + return s.size; }; diff --git a/solution/0900-0999/0929.Unique Email Addresses/Solution.py b/solution/0900-0999/0929.Unique Email Addresses/Solution.py index 4461e6f9e6e39..75ae976976ecb 100644 --- a/solution/0900-0999/0929.Unique Email Addresses/Solution.py +++ b/solution/0900-0999/0929.Unique Email Addresses/Solution.py @@ -2,9 +2,13 @@ class Solution: def numUniqueEmails(self, emails: List[str]) -> int: s = set() for email in emails: - local, domain = email.split('@') - local = local.replace('.', '') - if (i := local.find('+')) != -1: - local = local[:i] - s.add(local + '@' + domain) + local, domain = email.split("@") + t = [] + for c in local: + if c == ".": + continue + if c == "+": + break + t.append(c) + s.add("".join(t) + "@" + domain) return len(s) diff --git a/solution/0900-0999/0929.Unique Email Addresses/Solution.rs b/solution/0900-0999/0929.Unique Email Addresses/Solution.rs index 32f5442f5ca04..068ea93e80fbf 100644 --- a/solution/0900-0999/0929.Unique Email Addresses/Solution.rs +++ b/solution/0900-0999/0929.Unique Email Addresses/Solution.rs @@ -1,23 +1,26 @@ use std::collections::HashSet; + impl Solution { pub fn num_unique_emails(emails: Vec) -> i32 { - let mut set = HashSet::new(); - for email in emails.iter() { - let res: Vec<&str> = email.split('@').collect(); - let mut s = String::new(); - for &c in res[0].as_bytes().iter() { - if c == b'.' { + let mut s = HashSet::new(); + + for email in emails { + let parts: Vec<&str> = email.split('@').collect(); + let local = parts[0]; + let domain = parts[1]; + let mut t = String::new(); + for c in local.chars() { + if c == '.' { continue; } - if c == b'+' { + if c == '+' { break; } - s.push(c as char); + t.push(c); } - s.push('@'); - s.push_str(res[1]); - set.insert(s); + s.insert(format!("{}@{}", t, domain)); } - set.len() as i32 + + s.len() as i32 } } diff --git a/solution/0900-0999/0929.Unique Email Addresses/Solution.ts b/solution/0900-0999/0929.Unique Email Addresses/Solution.ts index 2ce7c64739501..82c2352b9da6d 100644 --- a/solution/0900-0999/0929.Unique Email Addresses/Solution.ts +++ b/solution/0900-0999/0929.Unique Email Addresses/Solution.ts @@ -1,7 +1,18 @@ function numUniqueEmails(emails: string[]): number { - return new Set( - emails - .map(email => email.split('@')) - .map(([start, end]) => start.replace(/\+.*|\./g, '') + '@' + end), - ).size; + const s = new Set(); + for (const email of emails) { + const [local, domain] = email.split('@'); + let t = ''; + for (const c of local) { + if (c === '.') { + continue; + } + if (c === '+') { + break; + } + t += c; + } + s.add(t + '@' + domain); + } + return s.size; }