Problem overview
The function findTheDifference receives two strings. The string t is the string s with its letters shuffled and one extra letter inserted somewhere. The function returns that extra letter as a rune. Both strings hold only lowercase English letters, and s can be empty.
With s = "abcd" and t = "abcde", the letters a to d each appear once in both strings, and e appears only in t, so the answer is 'e'. With s = "" and t = "y", the answer is 'y'.
Approach: compare letter counts
The extra letter can't be found by asking whether it appears in s. It may well appear there already: with s = "aab" and t = "abaa" the extra letter is another a. What gives it away is the count. For every letter except the extra one, t holds exactly as many copies as s. For the extra letter, t holds one more.
That suggests the most direct plan. Take each letter of t, count how often it occurs in s and in t, and return the first letter whose two counts differ. The extra letter always passes through that test, and no other letter does, so the first mismatch is the answer.
This is a brute-force solution. Counting walks a whole string, and it happens for every letter of t, so the work grows with the square of the length. The lessons that follow on this problem count each string only once.
Step by step
- Write a counting helper named
countChar. It takes a string and aruneand returns anint. The main function uses it twice per letter, once onsand once ont, so it is worth having as its own function. - Start a counter at 0 with
count := 0. - Loop over the string with
for _, ch := range s. The_discards the index, because only the letters matter. - Compare each letter to the one being counted with
ch == c. - Add one to
counton a match. - Return the total after the loop.
- In
findTheDifference, loop overt. The extra letter is intby definition, sotis the string to scan. - Compare the two counts for the current letter:
countChar(s, i) != countChar(t, i). A difference means this letter has more copies int. - Return the letter on a mismatch, and add a fallback return after the loop. Go insists that every path through a function with a result ends in a
return, even though the constraints guarantee that the loop always returns.
The solution in Go
func countChar(s string, c rune) int {
count := 0
for _, ch := range s {
if ch == c {
count++
}
}
return count
}
func findTheDifference(s string, t string) rune {
for _, i := range t {
if countChar(s, i) != countChar(t, i) {
return i
}
}
return ' '
}
The Go details worth a closer look:
rangeover a string yields runes. Each step offor _, ch := range sgives the next character as arune, which is an alias forint32. That is why the helper's second parameter is arune: it has the same type asch.- Indexing yields bytes. Writing the helper with
for i := 0; i < len(s); i++and comparings[i] == cdoes not compile: the compiler reportsinvalid operation: s[i] == c (mismatched types byte and rune). Go never converts between integer types implicitly. For lowercase English letters, bytes and runes hold the same numbers, but the types must still agree. - The result is a number. The function returns a
rune, sofmt.Println(findTheDifference("abcd", "abcde"))prints101, the code ofe. To print the letter, usefmt.Printf("%c", r)orstring(r). - The fallback value. Without the final
return ' ', the code fails withmissing return. The space character is arbitrary. It is never returned for valid input. - Unused names are errors. A declared variable that is never used, or an import that is never used, stops the build in Go. Here every name is used.
Complexity
Time: O(n²), where n is the length of s. The loop in findTheDifference runs at most n + 1 times, and each pass calls countChar twice. Each call walks a whole string of about n letters. In the worst case, when the extra letter comes last in t, every letter is checked. With the constraint of 1,000 letters, that is a few million steps, which is fast, but the growth is quadratic.
Space: O(1). The function keeps a few integers and allocates nothing.
Edge cases and common mistakes
- Empty
s. The loop runs once over a single letter, the count insis 0 and the count intis 1, so that letter is returned. - The extra letter repeats an existing one.
s = "aab"andt = "abaa"returna. Counts catch this, while a membership test would not. - Scanning
sinstead oft. The extra letter might not appear insat all, so the loop would never meet it. - Mixing bytes and runes. Keep the helper's parameter and the loop variable both as runes, as in the solution.
- Recounting is the cost. A repeated letter in
ttriggers the same two counts again. That repeated work is what the hash-table lesson removes.
Testing
s = "abcd",t = "abcde"givese.s = "",t = "y"givesy.s = "aab",t = "abaa"givesa.
