本文已参与「新人创作礼」活动,一起开启掘金创作之路。
929. 独特的电子邮件地址
难度简单183
每个 有效电子邮件地址 都由一个 本地名 和一个 域名 组成,以 '@' 符号分隔。除小写字母之外,电子邮件地址还可以含有一个或多个 '.' 或 '+' 。
- 例如,在
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
思路
先去掉本地名第一个加号之后的部分
再去掉本地名中所有的句点
ac代码
class Solution {
public int numUniqueEmails(String[] emails) {
Set<String> set = new HashSet<String>();
for (String email : emails) {
int i = email.indexOf('@');
String s = email.substring(0, i).split("\\+")[0];
s = s.replace(".", "");
set.add(s + email.substring(i));
}
return set.size();
}
}
双指针算法
class Solution {
public int numUniqueEmails(String[] emails) {
Set<String> set = new HashSet<>();
for (String email : emails) {
set.add(transfer(email));
}
return set.size();
}
private String transfer(String email) {
//转数组
char[] str = email.toCharArray();
int n = str.length;
//双指针,pos是修改后的,i是原来的
int i = 0, pos = 0;
//没碰到+或@
while (i < n && str[i] != '+' && str[i] != '@') {
//ch=str[i],然后i后移。
char ch = str[i++];
//若不是点,就将数组的pos位替换为ch,然后pos++,是点的话,pos不变,然后下次循环i后移。
if (ch != '.') {
str[pos++] = ch;
}
}//循环结束,点已经被删除完了。此时i可能是+或@,pos指向有效字符的下一位。(这一位是前面i已经遍历过的,后续可以直接替换掉。)
//如果i是+
if (str[i] == '+') {
//将i指向@位置。从i开始查找更高效。
i = email.indexOf('@', i);
}
//数组复制,从str的第i位开始(包括它),复制n-i位(即复制到了末尾),然后粘贴到str的pos位之后(含pos位,也就是第i位放到了第pos位,后面顺延)。
System.arraycopy(str, i, str, pos, n - i);
//复制完之后,我们想要的数组也就是从0开始,一直到pos+n-i-1了,即length=pos+n-i-1-0+1=pos+n-i;
//构造字符串返回即可。
return new String(str, 0, pos + n - i);
}
}