Leetcode 831. Masking Personal Information
Problem Explanation
Given a string representing personal information (either an email or a phone number), we are asked to return a "masked" version of the personal information, to protect the sensitive data. The problem provides specific rules for masking both emails and phone numbers.
For an email, we need to turn it all in lowercase, retain the first and last letters of the first name and replace everything between the first and last letters of the first name with five '*'.
For a phone number, we need to keep only the last 4 digits from the local number, replace all other digits with '*', and add '-' for formatting, keeping in mind the country code is optional.
Solution Approach
For this problem, we will determine whether the input string is an email or a phone number and then apply the corresponding masking rules. This can be done efficiently using the built-in string and list methods provided by most programming languages.
A simple approach would be:
-
To identify emails: If we find an '@' in our string, we lower case the string, separate the first character, add 5 '*' and concatenate it with the original string starting from (index_of'@'-1).
-
To identify phone numbers: If there is no '@', we know it's a phone number. We then remove anything that's not a digit from our string. Now for the case of local numbers (10 digits) and international numbers (more than 10 digits), we create the necessary string format.
Python Solution
1
2python
3class Solution:
4 def maskPII(self, s: str) -> str:
5 if '@' in s:
6 first, after = s.split('@')
7 return "{}*****{}@{}".format(first[0], first[-1], after).lower()
8
9 digits = [i for i in s if i.isdigit()]
10 local = "***-***-" + "".join(digits[-4:])
11 if len(digits) == 10:
12 return local
13 return "+" + "*" * (len(digits) - 10) + "-" + local
Java Solution
1 2java 3class Solution { 4 public String maskPII(String s) { 5 int atIndex = s.indexOf('@'); 6 if (atIndex >= 0) { 7 s = s.toLowerCase(); 8 return s.charAt(0) + "*****" + s.substring(atIndex - 1); 9 } 10 String digits = s.replaceAll("\\D+", ""); 11 String local = "***-***-" + digits.substring(digits.length() - 4); 12 if (digits.length() == 10) return local; 13 String intl = '+' + String.join("", Collections.nCopies(digits.length() - 10, "*")) + '-'; 14 return intl + local; 15 } 16}
JavaScript Solution
1
2javascript
3class Solution {
4 maskPII(S) {
5 if (S.indexOf('@') > -1) {
6 S = S.toLowerCase();
7 return S.charAt(0) + "*****" + S.slice(S.indexOf('@') - 1);
8 }
9 S = S.replace(/\D/g, '');
10 return (S.length > 10 ? '+' + '*'.repeat(S.length - 10) + '-' : '') + "***-***-" + S.slice(-4);
11 };
12};
C++ Solution
1
2cpp
3class Solution {
4public:
5 string maskPII(string s) {
6 int atIndex = s.find('@');
7 if (atIndex != std::string::npos) {
8 std::transform(s.begin(), s.end(), s.begin(), ::tolower);
9 return s.substr(0, 1) + "*****" + s.substr(atIndex - 1);
10 }
11 std::string res;
12 for(const char c : s) {
13 if(isdigit(c))
14 res += c;
15 }
16 if(res.length() == 10)
17 return "***-***-" + res.substr(res.length()-4);
18 return '+' + std::string(res.length()-10,'*') + "-***-***-" + res.substr(res.length()-4);
19 }
20};
C# Solution
1 2csharp 3public class Solution { 4 public string MaskPII(string S) { 5 int atIndex = S.IndexOf('@'); 6 if (atIndex >= 0) { 7 S = S.ToLower(); 8 return S[0] + "*****" + S.Substring(atIndex - 1); 9 } 10 string digits = string.Join("", S.Where(Char.IsDigit)); 11 string local = "***-***-" + digits.Substring(digits.Length - 4); 12 if (digits.Length == 10) return local; 13 string intl = '+' + new String('*', digits.Length - 10) + '-'; 14 return intl + local; 15 } 16}
Ruby Solution
1 2ruby 3class Solution 4 def mask_pii(s) 5 at_index = s.index('@') 6 if at_index != nil 7 s = s.downcase() 8 return s[0] + "*****" + s[at_index - 1, s.length] 9 end 10 digits = s.gsub(/[^0-9]/, '') 11 local = "***-***-" + digits[digits.length - 4, digits.length] 12 if digits.length == 10 13 return local 14 end 15 intl = '+' + '*' * (digits.length - 10) + '-' 16 return intl + local 17 end 18end
The Ruby solution applies the same steps: first, it checks if the string includes '@'. If so, it masks the email. If it doesn't include '@', it cleans the string to only include numbers and proceeds to mask the phone number. If the phone number includes a country code (more than 10 digits), it adds the appropriate number of asterisks.
Scala Solution
1
2scala
3class Solution {
4 def maskPII(s: String): String = {
5 if (s.indexOf('@') >= 0) {
6 val lower = s.toLowerCase()
7 lower.head + "*****" + lower.substring(lower.indexOf('@') - 1)
8 } else {
9 val phoneDigits = s.filter(_.isDigit)
10 val local = "***-***-" + phoneDigits.takeRight(4)
11 if (phoneDigits.length > 10) "+" + "*" * (phoneDigits.length - 10) + "-" + local
12 else local
13 }
14 }
15}
The Scala solution uses the built-in indexOf
method to locate the '@' character in the string. If '@' is found, we are dealing with an email, pass it to the lowercase and mask the necessary parts. If '@' is not found, we filter out all characters that are not digits and treat the result as a phone number, to mask the appropriate parts. If the phone number is more than 10 digits long, it must include a country code, which we account for in our return statement.
All these solutions demonstrate standard usage of string and list methods, with minor differences due to language-specific syntax. They handle both provided cases ('@' present or not) and accomplish the task effectively and efficiently.
Got a question?ย Ask the Teaching Assistantย anything you don't understand.
Still not clear? Ask in the Forum, ย Discordย orย Submitย the part you don't understand to our editors.