LeetCode: 929 Unique Email Addresses

Every valid email consists of a local name and a domain name, separated by the '@' sign. Besides lowercase letters, the email may contain one or more '.' or '+'.

  • For example, in "[email protected]", "alice" is the local name, and "leetcode.com" is the domain name.
  • If you add periods (.) between some characters in the local name part of an email address, mail sent there will be forwarded to the same address without dots in the local name. For example, "[email protected]" and "[email protected]" forward to the same email address.
  • If you add a plus (+) in the local name, everything after the first plus sign will be ignored. This allows certain emails to be filtered. For example, "[email protected]" will be forwarded to "[email protected]".

Given an array of strings emails where each emails[i] is a valid email, return the number of different addresses that actually receive emails.

Example

Input: emails = ["[email protected]", "[email protected]", "[email protected]"]
Output: 2
Explanation: "[email protected]" and "[email protected]" are the two different addresses that actually receive emails.

问题

每个有效的电子邮件地址由 本地名域名 组成,中间用 '@' 符号分隔。除了小写字母,邮件地址还可能包含一个或多个 '.''+'

  • 例如,在 "[email protected]" 中,"alice" 是本地名,"leetcode.com" 是域名。
  • 如果在本地名部分中加入句点 (.),邮件仍然会发送到同一个地址(本地名中没有句点)。例如,"[email protected]""[email protected]" 会被转发到同一个邮箱地址。
  • 如果在本地名中添加加号 (+),加号后的所有内容都会被忽略。这可以用来过滤邮件。例如,"[email protected]" 会被转发到 "[email protected]"

给定一个字符串数组 emails,其中每个 emails[i] 是有效的电子邮件地址,返回实际接收邮件的不同地址的数量。

例子

输入: emails = ["[email protected]", "[email protected]", "[email protected]"]
输出: 2
解释: "[email protected]" 和 "[email protected]" 是实际接收邮件的两个不同地址。

Iterative Solution

Approach: String Manipulation and Set / 字符串操作和集合

The key idea is to normalize each email address by removing dots from the local name and ignoring any characters after a plus sign. We can then store the normalized email addresses in a set, as sets automatically handle duplicates.

Approach Explanation / 方法解释

  1. Split by ‘@’: Split the email into the local name and the domain name.
  2. Process Local Name: For the local name, remove everything after the first plus sign and delete any periods (.).
  3. Store in Set: Combine the processed local name with the domain name, and store the result in a set to eliminate duplicates.
  4. Return the Count: Return the size of the set, which represents the number of unique email addresses.

Iterative Algorithm / 迭代算法

  1. Initialize an empty set to store unique email addresses.
  2. For each email in the emails list:
    • Split the email into the local name and domain name.
    • Remove dots from the local name.
    • Ignore everything after the first plus sign in the local name.
    • Add the normalized email to the set.
  3. Return the size of the set.

Iterative Implementation / 迭代实现

class Solution:
    def numUniqueEmails(self, emails: List[str]) -> int:
        unique_emails = set()

        for email in emails:
            local, domain = email.split('@')
            local = local.split('+')[0].replace('.', '')
            unique_emails.add(local + '@' + domain)

        return len(unique_emails)

Iterative Solution Explanation / 迭代解决方案解释

  1. Initialize Set for Unique Emails / 初始化集合以存储唯一邮件

    unique_emails = set()
    • English: Create an empty set to store the unique email addresses.
    • Chinese: 创建一个空集合来存储唯一的电子邮件地址。
  2. Process Each Email / 处理每个电子邮件

    for email in emails:
       local, domain = email.split('@')
       local = local.split('+')[0].replace('.', '')
       unique_emails.add(local + '@' + domain)
    • English: For each email, split it into the local and domain parts. Remove any dots and ignore characters after the plus sign in the local name.
    • Chinese: 对于每个电子邮件,将其拆分为本地名和域名部分。删除本地名中的所有句点,并忽略加号后的字符。
  3. Return the Size of the Set / 返回集合的大小

    return len(unique_emails)
    • English: Return the number of unique email addresses by returning the size of the set.
    • Chinese: 返回唯一电子邮件地址的数量,方法是返回集合的大小。

Recursive Solution

Approach: Recursive Processing of Emails / 递归处理电子邮件

We can also implement the same approach recursively. For each email, we recursively process the local name by removing dots and ignoring everything after the plus sign. The normalized email is then stored in a set, and the recursion continues until all emails are processed.

Recursive Algorithm / 递归算法

  1. Base Case: If no emails are left to process, return the size of the set.
  2. For each email, split the local and domain parts, normalize the local name, and add the normalized email to the set.
  3. Recursively process the rest of the emails.

Recursive Implementation / 递归实现

class Solution:
    def numUniqueEmails(self, emails: List[str]) -> int:
        def process(emails, unique_emails):
            if not emails:
                return len(unique_emails)

            email = emails[0]
            local, domain = email.split('@')
            local = local.split('+')[0].replace('.', '')
            unique_emails.add(local + '@' + domain)

            return process(emails[1:], unique_emails)

        return process(emails, set())

Recursive Solution Explanation / 递归解决方案解释

  1. Base Case: No More Emails / 基本情况:没有更多电子邮件

    if not emails:
       return len(unique_emails)
    • English: If there are no more emails to process, return the size of the set.
    • Chinese: 如果没有更多电子邮件需要处理,返回集合的大小。
  2. Process the Current Email / 处理当前电子邮件

    email = emails[0]
    local, domain = email.split('@')
    local = local.split('+')[0].replace('.', '')
    unique_emails.add(local + '@' + domain)
    • English: For the current email, split it into local and domain parts, normalize the local name, and add the email to the set.
    • Chinese: 对于当前电子邮件,将其拆分为本地名和域名部分,标准化本地名,并将其添加到集合中。
  3. Recursive Call to Process Remaining Emails / 递归调用以处理剩余的电子邮件

    return process(emails[1:], unique_emails)
    • English: Recursively process the remaining emails.
    • Chinese: 递归处理剩余的电子邮件。

Complexity Analysis / 复杂度分析

  • Time Complexity / 时间复杂度: O(n * m), where n is the number of emails and m is the average length of an email. We process each email once.
  • Space Complexity / 空间复杂度:
    • Iterative Solution: O(n), due to the space required for the set.
    • Recursive Solution: O(n), due to the recursion stack and the set.

Key Concept / 关键概念

  • String Manipulation / 字符串操作: Both the iterative and recursive solutions rely on splitting and modifying strings to normalize the email addresses.
  • Recursion / 递归: The recursive solution processes each email one by one, breaking the problem down into smaller parts.

Summary / 总结

  • English: We can solve the problem of finding unique email addresses

    by normalizing each email, removing dots from the local name, and ignoring characters after the plus sign. Both iterative and recursive solutions achieve the same result.

  • Chinese: 我们可以通过标准化每个电子邮件地址来解决寻找唯一电子邮件的问题,删除本地名中的句点,并忽略加号后的字符。迭代和递归解决方案都能达到相同的结果。

Tips / 提示

  • English: Be sure to correctly handle emails that don’t contain a plus sign, as the entire local name should be retained in that case.
  • Chinese: 确保正确处理不包含加号的电子邮件,在这种情况下应保留整个本地名。

5 More Similar Questions / 推荐5问题

  1. LeetCode 811. Subdomain Visit Count
  2. LeetCode 804. Unique Morse Code Words
  3. LeetCode 929. Unique Email Addresses
  4. LeetCode 482. License Key Formatting
  5. LeetCode 1170. Compare Strings by Frequency of the Smallest Character

Recommended Resources / 推荐资源

  • English: Practice problems related to string manipulation to get comfortable with handling various string operations efficiently.
  • Chinese: 练习与字符串操作相关的问题,以熟练高效地处理各种字符串操作。

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *