For the following coding puzzle, I only scored 50% because of 1) performance and 2) completness
My solution:
HashSet<char> seenLowerCaseLetters = new HashSet<char>(); HashSet<char> seenUpperCaseLetters = new HashSet<char>(); HashSet<char> invalidLetters = new HashSet<char>(); foreach (char s in stringToTest) { // Lower Case if(char.IsLower(s)) { if (!seenLowerCaseLetters.Contains(s)) { seenLowerCaseLetters.Add(s); // If Upper case equivalent has been seen, then remove and prevent further addition of this letter if (seenUpperCaseLetters.Contains(char.ToUpper(s))) { invalidLetters.Add(char.ToUpper(s)); seenUpperCaseLetters.Remove(char.ToUpper(s)); } } // If we've already seen this lower case letter, then try remove from upper case as it would be invalid else if(seenLowerCaseLetters.Contains(s)) seenUpperCaseLetters.Remove(char.ToUpper(s)); } // Lower Case else if (char.IsUpper(s)) { // if lower case hasn't been seen already then it can never be a valid letter if(!seenLowerCaseLetters.Contains(char.ToLower(s))) invalidLetters.Add(char.ToUpper(s)); // If lower case has been seen and it's not an invalid letter, add. if (seenLowerCaseLetters.Contains(char.ToLower(s)) && !invalidLetters.Contains(s)) seenUpperCaseLetters.Add(s); } } return seenUpperCaseLetters.Count;
Alternative solution:
Dictionary<char, int> lowerCaseCount = new Dictionary<char, int>(); for(int i = 0; i < stringToTest.Length; i++) { char c = stringToTest[i]; if(char.IsLower(c)) { if (!lowerCaseCount.ContainsKey(c)) lowerCaseCount.Add(c, 1); if (lowerCaseCount[c] == 2) lowerCaseCount[c] = -1; } else { char cLower = char.ToLower(stringToTest[i]); if (!lowerCaseCount.ContainsKey(cLower)) lowerCaseCount.Add(cLower, -1); if (lowerCaseCount[cLower] == 1) lowerCaseCount[cLower] = 2; } } int count = 0; foreach(char c in lowerCaseCount.Keys) { if (lowerCaseCount[c] == 2) count++; } return count;
Questions:
- Is the alternative solution much faster?
- What edge cases have I missed based on the question?
Regarding the performance I can see to a certain point why the alternative is a bit faster but I didn't think HashSets were much slower than arrays.
And I can't see what edge cases are missing.
Thanks