Problem overview
The string t is s shuffled, plus one extra lowercase letter inserted at a random position. findTheDifference returns the extra letter as a char. The string s can be empty and t is exactly one character longer.
For s = "abcd" and t = "abcde" the result is 'e'. For s = "" and t = "y" it is 'y'.
This lesson asks for O(n) time and O(1) extra space, where n is the length of t. That rules out counting letters in a hash table whose size depends on the input, and it points to a trick with bitwise XOR.
Approach: let paired letters cancel out
XOR, written ^ in C++, combines two integers bit by bit: each result bit is 1 when the two input bits differ. Two properties matter here:
x ^ x = 0: any value XORed with itself gives zero.x ^ 0 = x: XOR with zero changes nothing.
XOR is also commutative and associative, so the order in which values are combined doesn't matter.
Now XOR every character of s and every character of t into one accumulator. Each letter of s appears once in s and once in its shuffled copy inside t, so every such pair cancels to zero, wherever the letters sit in the strings. The only letter without a partner is the extra one in t, and what is left in the accumulator is exactly that letter.
Repeated letters work the same way. With s = "aab" and t = "abaa", the letters XORed together are a, a, b, a, b, a, a. That is five copies of a (three from t and two from s) and two of b. The two bs cancel, four of the five as cancel, and one a remains.
The method needs one variable and two passes, so the extra space is constant and the time is O(n).
Step by step
- Declare
char result = 0. Zero is the identity for XOR, so the accumulator starts out neutral. - Loop over
swith a range-basedfor, naming each characterc. - XOR each character into
resultwith^=. - Loop over
tthe same way. - XOR each of its characters into
resultas well. After this loop every letter that occurs in both strings has been combined twice per pair and has cancelled. - Return
result. It holds the extra letter, so no fallback return is needed.
The solution in C++
class Solution {
public:
char findTheDifference(string s, string t) {
char result = 0;
for (char c : s) {
result ^= c;
}
for (char c : t) {
result ^= c;
}
return result;
}
};
C++ details worth a closer look:
- Characters are integers. A
charholds a character code, such as 97 for'a', so XOR works on it directly. In an expression, both operands of^are first promoted toint. - Compound assignment narrows for you.
result ^= ccomputes the XOR as anintand stores it back into thechar. Writingresult = result ^ ccompiles too, but a narrowing frominttocharis easier to notice there. Because the inputs are lowercase letters, with codes from 97 to 122, every value stays well inside the range of achar, whethercharis signed or unsigned on the platform. - Both strings, one accumulator. The order of the two loops doesn't matter. You could also loop over
tfirst, or interleave the work in a single loop overtwith an index intos. - No fallback return. Unlike the counting solutions, this function has no early return inside a loop, so the last line is the only exit.
- Strings by value. The parameters are copies of the caller's strings. The method only reads them.
Complexity
Time: O(n). The loops run n - 1 and n times, and each step is one XOR.
Space: O(1) extra. The only added storage is the char result. The by-value string parameters are copies made by the call itself, and taking them as const string& would avoid that cost as well.
Edge cases and common mistakes
- Empty
s. The first loop does nothing, and the second leaves exactly the single character oft, so'y'comes back fort = "y". - The extra letter is a duplicate. With
s = "a"andt = "aa"the threeas XOR to'a'. No special case is needed, which is the strength of this method. - Skipping one of the strings. XORing only
tgives the XOR of all its letters, not the extra one. Both strings must go into the accumulator. - Starting from a non-zero value. The accumulator must start at 0. Any other start leaves a stray value in the result.
- Using
+or-instead of^. Addition doesn't cancel pairs, so summing both strings just adds everything up. Subtracting the sum ofsfrom the sum oftdoes give the extra letter's code, but that is a different technique, and XOR avoids any question of overflow. - Input outside the contract. The result is only meaningful when
treally is a shuffle ofsplus one letter. With other inputs XOR just returns the XOR of the unmatched characters.
Testing
s = "abcd",t = "abcde"gives'e'.s = "",t = "y"gives'y'.s = "aab",t = "abaa"gives'a'.s = "a",t = "ab"gives'b'.
