Problem overview
You get two strings, s and t. The string t was made by shuffling the letters of s and inserting one extra letter somewhere. The method findTheDifference must return that extra letter as a Char.
For s = "abcd" and t = "abcde", the letters a, b, c and d each appear once in both strings, while e appears once in t and never in s. The answer is 'e'. For s = "" and t = "y", the answer is 'y', because t is nothing but the added letter.
Both strings contain only lowercase letters, and s can be empty, with at most 1000 characters. The shuffling means the extra letter can be anywhere in t, so looking at the last character is not enough.
Approach: compare letter counts
The extra letter is the one that occurs more often in t than in s. If the added letter is a brand-new one, it occurs once in t and zero times in s. If it duplicates a letter already in s, say s = "aab" and t = "abaa", the count of a rises from two to three. In both cases exactly one letter has different counts in the two strings, and every other letter has equal counts.
That gives a direct plan. Take each character of t, count how often it occurs in s and in t, and return the first one where the two counts differ. Counting is a small loop, so it goes into a helper method, countChar.
This is the brute-force version. Every call to countChar walks a whole string, and the main loop makes two calls per character of t. With n the length of t, that is about 2n walks of up to n characters each, so the time is O(n²). For strings of at most 1001 characters that is fast enough, and the idea is easy to get right. Later lessons on this problem keep the counts in a hash map, and then in a single number, to reach O(n).
Step by step
- Define the helper.
countChar(s: String, c: Char): Intbelongs to theSolutionclass, abovefindTheDifference. It answers one question: how many times doescoccur ins? - Start a counter. A
var count = 0holds the running total. It must be avarbecause it changes. - Loop over the string.
for (ch <- s)gives each character in turn, as aChar. - Compare and increment. When
ch == c, add one tocount. Then the loop ends and the method returnscount. - Loop over
tin the main method. The extra letter is certainly a character oft, so these are the only candidates worth testing. - Test each candidate. If
countChar(s, i) != countChar(t, i), the letter occurs a different number of times in the two strings. It can only be the added one, so return it. - Add a fallback. After the loop the method returns a space. Scala needs a
Charon every path, and the compiler can't know the loop always returns. With valid input the fallback is never reached.
The solution in Scala
class Solution {
def countChar(s: String, c: Char): Int = {
var count = 0
for (ch <- s) {
if (ch == c) {
count += 1
}
}
return count
}
def findTheDifference(s: String, t: String): Char = {
for (i <- t) {
if (countChar(s, i) != countChar(t, i)) {
return i
}
}
return ' '
}
}
The Scala details worth a closer look:
for (ch <- s)on aString. A string behaves like a sequence of characters, so aforloop can walk it directly. The loop variable has typeChar, which is whych == ccompares two characters.==compares values. ForCharand for strings,==checks equality of contents, so there is nothing like Java's reference comparison to worry about.returninside the loop. The body of aforloop is a function that Scala passes toforeach, andreturninside it still leaves the whole method. Scala 3.5 accepts this but reports a warning that non-local returns are no longer supported. The idiomatic alternatives avoid the loop, for examplet.find(c => countChar(s, c) != countChar(t, c)), which returns anOption[Char].- The return type. The method is declared to return
Char, so every path ends in aChar. A barereturn iwithiaCharfits, and so does the fallback' ', a character literal in single quotes. A string literal in double quotes would not compile there. - Counting without a helper. A shorter way to write
countChariss.count(_ == c). The lesson writes the loop out so you can see what the counting does.
Complexity
Time: O(n²). countChar costs time proportional to the length of its string. The main loop runs at most n times with two calls each, and every call walks up to n characters. The loop can end early, but in the worst case the extra letter sits at the end of t.
Space: O(1). Only a few integers and a character exist at any time. No copy of either string is made.
Edge cases and common mistakes
- Empty
s. Withs = "",countChar(s, i)is 0 for every character, andthas one character with a count of 1. The first iteration returns it. - The extra letter duplicates an existing one. For
s = "aab"andt = "abaa", the count ofais 2 insand 3 int, so'a'is returned. Checking only whether the letter appears inswould fail here. - Looking at
sinstead oft. Looping overscan miss a brand-new letter, because that letter is not insat all. Loop overt. - Returning a
String. The result is aChar, written'e', not"e". - A
valcounter.count += 1on avalis a compile error, so the counter has to be avar.
Testing
s = "abcd",t = "abcde"returns'e'.s = "",t = "y"returns'y'.s = "abcd",t = "dbeca"returns'e'.countChar("banana", 'a')returns 3.
