Description

每個電子郵件地址由 local name 和 domain name 組成,以 @ 分隔。規則:local name 中的 . 被忽略,+ 及其後面的字元被忽略。回傳不同實際地址的數量。

Example:

Input: emails = [“test.email+alex@leetcode.com”,“test.e.mail+bob.cathy@leetcode.com”,“testemail+david@lee.tcode.com”] Output: 2

Intuition#

核心思路:對每個 email 按規則處理 local name(去 .、截斷 + 後面),再用 Set 去重計數。

  • 先用 @ 分割出 local 和 domain
  • local 部分:移除所有 .,截斷 + 後面的內容
  • 把處理後的完整地址加入 Set

Approaches#

1: 字串處理 + 手動解析#

  • 概念: 手動遍歷 local name 的每個字元,遇到 . 跳過,遇到 + 停止
  • 時間複雜度: O(n * m) - n 為 email 數量,m 為平均長度
  • 空間複雜度: O(n * m) - Set 儲存
class Solution {
    fun numUniqueEmails(emails: Array<String>): Int {
        val unique = HashSet<String>()
        for (email in emails) {
            val parts = email.split("@")
            val local = parts[0]
            val domain = parts[1]
            val sb = StringBuilder()
            for (c in local) {
                if (c == '.') continue
                if (c == '+') break
                sb.append(c)
            }
            unique.add("$sb@$domain")
        }
        return unique.size
    }
}

⭐2: 使用內建函式#

  • 概念: 用 splitreplacesubstringBefore 等內建函式簡潔處理
  • 時間複雜度: O(n * m)
  • 空間複雜度: O(n * m)
class Solution {
    fun numUniqueEmails(emails: Array<String>): Int {
        val unique = HashSet<String>()
        for (email in emails) {
            val (local, domain) = email.split("@")
            val cleanLocal = local.substringBefore("+").replace(".", "")
            unique.add("$cleanLocal@$domain")
        }
        return unique.size
    }
}

🔑 Takeaways#

  • Pattern: 字串處理 + Hash Set 去重
  • 關鍵技巧: 善用 substringBeforereplace 等 Kotlin 內建函式簡化程式碼;注意規則只適用於 local name,domain 不處理