跳转至

3860. 不同邮件组 🔒

题目描述

给定一个字符串数组 emails,其中每个字符串是一个有效的邮件地址。

如果两个邮件地址的 规范化 本地名称和 规范化 域名名称 都相同,则属于同一组。

规范化规则如下:

  • 本地名称是 '@' 符号 之前 的部分。
    • 忽略所有点 '.'
    • 忽略第一个 '+' 之后的所有内容,如果存在的话。
    • 转换为小写。
  • 域名是 '@' 符号 后面 的部分。
    • 转换为小写。

返回一个整数,表示规范化后的 不同 电子邮件组的数量。

 

示例 1:

输入:emails = ["test.email+alex@leetcode.com", "test.e.mail+bob.cathy@leetcode.com", "testemail+david@lee.tcode.com"]

输出:2

示例:

邮件地址 本地名称 规范化本地名称 域名 规范化域名 最终邮件地址
test.email+alex@leetcode.com test.email+alex testemail leetcode.com leetcode.com testemail@leetcode.com
test.e.mail+bob.cathy@leetcode.com test.e.mail+bob.cathy testemail leetcode.com leetcode.com testemail@leetcode.com
testemail+david@lee.tcode.com testemail+david testemail lee.tcode.com lee.tcode.com testemail@lee.tcode.com

不同的邮件地址是 ["testemail@leetcode.com", "testemail@lee.tcode.com"]。因此,答案是 2。

示例 2:

输入:emails = ["A@B.com", "a@b.com", "ab+xy@b.com", "a.b@b.com"]

输出:2

示例:

邮件地址 本地名称 规范化本地名称 域名 规范化域名 最终邮件地址
A@B.com A a B.com b.com a@b.com
a@b.com a a b.com b.com a@b.com
ab+xy@b.com ab+xy ab b.com b.com ab@b.com
a.b@b.com a.b ab b.com b.com ab@b.com

不同的邮件地址是 ["a@b.com", "ab@b.com"]。因此,答案是 2。

示例 3:

输入:emails = ["a.b+c.d+e@DoMain.com", "ab+xyz@domain.com", "ab@domain.com"]

输出:1

解释:

邮件地址 本地名称 规范化本地名称 域名 规范化域名 最终邮件地址
a.b+c.d+e@DoMain.com a.b+c.d+e ab DoMain.com domain.com ab@domain.com
ab+xyz@domain.com ab+xyz ab domain.com domain.com ab@domain.com
ab@domain.com ab ab domain.com domain.com ab@domain.com

所有邮件地址规范化为 "ab@domain.com"。因此,答案是 1。

 

提示:

  • 1 <= emails.length <= 1000
  • 1 <= emails[i].length <= 100
  • emails[i] 包含大小写英文字母,数字,以及字符 '.''+' 和 '@'
  • 每个 emails[i] 包含 恰好 一个 '@' 字符。
  • 所有本地名称和域名都不为空;本地名不能以 '+' 开头。
  • 域名以 ".com" 后缀结尾,并且在 ".com" 之前至少包含一个字符。

解法

方法一:哈希表

我们可以使用一个哈希表 \(\textit{st}\) 来存储每个邮箱地址的规范化结果。对于每个邮箱地址,我们按照题目要求进行规范化处理:

  • 将邮箱地址分为本地名和域名两部分。
  • 对于本地名,去掉所有的点 .,并且如果存在加号 +,则去掉加号及其后面的部分。最后将本地名转换为小写。
  • 对于域名,将其转换为小写。
  • 将规范化后的本地名和域名拼接起来,得到规范化后的邮箱地址,并将其加入哈希表 \(\textit{st}\) 中。

最后,哈希表 \(\textit{st}\) 中的元素个数即为唯一邮箱组的数量。

时间复杂度 \(O(n \cdot m)\),其中 \(n\)\(m\) 分别是邮箱地址的数量和每个邮箱地址的平均长度。空间复杂度 \(O(n \cdot m)\),最坏情况下所有邮箱地址都不同。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
class Solution:
    def uniqueEmailGroups(self, emails: list[str]) -> int:
        st = set()
        for email in emails:
            local, domain = email.split("@")
            local = local.split("+")[0].replace(".", "").lower()
            domain = domain.lower()
            normalized = local + domain
            st.add(normalized)
        return len(st)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Solution {
    public int uniqueEmailGroups(String[] emails) {
        Set<String> st = new HashSet<>();

        for (String email : emails) {
            String[] parts = email.split("@");
            String local = parts[0];
            String domain = parts[1];

            int plusIndex = local.indexOf('+');
            if (plusIndex != -1) {
                local = local.substring(0, plusIndex);
            }

            local = local.replace(".", "").toLowerCase();
            domain = domain.toLowerCase();

            String normalized = local + domain;
            st.add(normalized);
        }

        return st.size();
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class Solution {
public:
    int uniqueEmailGroups(vector<string>& emails) {
        unordered_set<string> st;

        for (auto& email : emails) {
            int atPos = email.find('@');
            string local = email.substr(0, atPos);
            string domain = email.substr(atPos + 1);

            int plusPos = local.find('+');
            if (plusPos != string::npos) {
                local = local.substr(0, plusPos);
            }

            string cleaned;
            for (char c : local) {
                if (c != '.') {
                    cleaned += tolower(c);
                }
            }

            for (char& c : domain) {
                c = tolower(c);
            }

            st.insert(cleaned + domain);
        }

        return st.size();
    }
};
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
func uniqueEmailGroups(emails []string) int {
    st := make(map[string]struct{})

    for _, email := range emails {
        parts := strings.Split(email, "@")
        local := parts[0]
        domain := parts[1]

        if idx := strings.Index(local, "+"); idx != -1 {
            local = local[:idx]
        }

        local = strings.ReplaceAll(local, ".", "")
        local = strings.ToLower(local)
        domain = strings.ToLower(domain)

        normalized := local + domain
        st[normalized] = struct{}{}
    }

    return len(st)
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
function uniqueEmailGroups(emails: string[]): number {
    const st = new Set<string>();

    for (const email of emails) {
        let [local, domain] = email.split('@');
        local = local.split('+')[0].replace(/\./g, '').toLowerCase();
        domain = domain.toLowerCase();

        const normalized = local + domain;
        st.add(normalized);
    }

    return st.size;
}

评论