Easy
题目描述
每个有效的电子邮件地址都由一个本地名和一个域名组成,用 ‘@’ 符号分隔。除了小写字母,电子邮件可能包含一个或多个 ‘.’ 或 ‘+’。
例如,在 “alice@leetcode.com” 中,“alice” 是本地名,“leetcode.com” 是域名。
如果在电子邮件地址的本地名部分中的某些字符之间添加句点 ‘.’,发送到那里的邮件将被转发到本地名中没有点的相同地址。注意,此规则不适用于域名。
例如,“alice.z@leetcode.com” 和 “alicez@leetcode.com” 转发到相同的电子邮件地址。
如果在本地名中添加加号 ‘+’,加号后的所有内容都将被忽略。这允许过滤某些电子邮件。注意,此规则不适用于域名。
例如,“m.y+name@email.com” 将被转发到 “my@email.com”。
可以同时使用这两个规则。
给定一个字符串数组 emails,我们会向 emails[i] 发送一封电子邮件。返回实际收到邮件的不同地址数量。
示例 1:
输入: emails = ["test.email+alex@leetcode.com","test.e.mail+bob.cathy@leetcode.com","testemail+david@lee.tcode.com"]
输出: 2
解释: "testemail@leetcode.com" 和 "testemail@lee.tcode.com" 实际收到邮件。
示例 2:
输入: emails = ["a@leetcode.com","b@leetcode.com","c@leetcode.com"]
输出: 3
提示:
- 1 <= emails.length <= 100
- 1 <= emails[i].length <= 100
- emails[i] 由小写英文字母、’+’, ‘.’ 和 ‘@’ 组成
- 每个 emails[i] 都包含一个 ‘@’ 字符
- 所有本地名和域名都非空
- 本地名不以 ‘+’ 字符开头
- 域名以 “.com” 后缀结尾
解题思路
解题思路
这是一道字符串处理题目,需要我们理解电子邮件地址的规范化规则:
- 分离本地名和域名:以 ‘@’ 为分隔符将邮件地址分为两部分
- 处理本地名规则:
- 遇到 ‘+’ 时,忽略后面所有字符
- 移除所有的 ‘.’ 字符
- 保持域名不变:域名部分不应用任何规则
- 统计唯一地址:使用哈希集合存储规范化后的地址
算法步骤:
- 遍历每个邮件地址
- 找到 ‘@’ 的位置,分离本地名和域名
- 对本地名进行规范化处理:
- 如果遇到 ‘+’,截取到 ‘+’ 之前的部分
- 移除所有的 ‘.’ 字符
- 将规范化后的地址添加到集合中
- 返回集合的大小
时间复杂度为 O(nm),其中 n 是邮件数量,m 是平均邮件长度。空间复杂度为 O(nm),用于存储规范化后的邮件地址。
代码实现
class Solution {
public:
int numUniqueEmails(vector<string>& emails) {
unordered_set<string> uniqueEmails;
for (const string& email : emails) {
int atPos = email.find('@');
string localName = email.substr(0, atPos);
string domainName = email.substr(atPos);
// 处理本地名
string processedLocal = "";
for (char c : localName) {
if (c == '+') {
break; // 忽略+后面的所有字符
}
if (c != '.') {
processedLocal += c; // 忽略句点
}
}
uniqueEmails.insert(processedLocal + domainName);
}
return uniqueEmails.size();
}
};
class Solution:
def numUniqueEmails(self, emails: List[str]) -> int:
unique_emails = set()
for email in emails:
local_name, domain_name = email.split('@')
# 处理本地名
# 先处理+号,忽略+后面的内容
if '+' in local_name:
local_name = local_name[:local_name.index('+')]
# 移除所有的句点
local_name = local_name.replace('.', '')
unique_emails.add(local_name + '@' + domain_name)
return len(unique_emails)
public class Solution {
public int NumUniqueEmails(string[] emails) {
HashSet<string> uniqueEmails = new HashSet<string>();
foreach (string email in emails) {
int atIndex = email.IndexOf('@');
string localName = email.Substring(0, atIndex);
string domainName = email.Substring(atIndex);
// 处理本地名
StringBuilder processedLocal = new StringBuilder();
foreach (char c in localName) {
if (c == '+') {
break; // 忽略+后面的所有字符
}
if (c != '.') {
processedLocal.Append(c); // 忽略句点
}
}
uniqueEmails.Add(processedLocal.ToString() + domainName);
}
return uniqueEmails.Count;
}
}
var numUniqueEmails = function(emails) {
const uniqueEmails = new Set();
for (let email of emails) {
const [local, domain] = email.split('@');
let cleanLocal = local.split('+')[0].replace(/\./g, '');
uniqueEmails.add(cleanLocal + '@' + domain);
}
return uniqueEmails.size;
};
复杂度分析
| 复杂度类型 | 复杂度 | 说明 |
|---|---|---|
| 时间复杂度 | O(n × m) | n 是邮件数量,m 是平均邮件长度,需要遍历每个邮件的每个字符 |
| 空间复杂度 | O(n × m) | 最坏情况下所有邮件地址都不同,需要存储 n 个长度为 m 的字符串 |