Editorial
Core insight
Find the Difference · Bit Manipulation Patterns
Core Insight for Find the Difference
The move from a sorting or hash map approach to Bit Manipulation relies on the specific properties of the XOR (Exclusive OR) operation, denoted by ^ or .
The key properties of XOR are:
- Self-Inverse: . (XORing a number with itself results in zero).
- Identity: . (XORing a number with zero leaves it unchanged).
- Commutative and Associative: The order in which we XOR numbers does not matter. .
Intuition:
If we treat the characters as integer ASCII values, we can XOR every character in s and every character in t into a single accumulator variable.
Because t contains all characters of s plus one extra, every character from s will be XORed twice (once from s, once from t). According to the Self-Inverse property, these pairs will cancel each other out to 0. The only value that will remain in the accumulator is the ASCII value of the added character, as it was XORed only once.
Visual Description:
Imagine a stream of bits flowing into a logic gate. When the character 'a' from s enters, it flips certain bits. When the matching 'a' from t enters later, it flips those exact same bits back to their original state. The system is stateful; it remembers the "parity" of the bits seen so far. After processing both strings entirely, the final state of the bits represents the binary code of the only character that did not trigger a second flip.
Deep dive
Full breakdown
Full reasoning, pitfalls, and implementation flow
LeetCode 389: Find the Difference Solution & Explanation
Problem Overview
TL;DR: The optimal solution utilizes the XOR bitwise operation to cancel out identical characters appearing in both strings, leaving only the added character remaining.
In the LeetCode 389 problem "Find the Difference," we are provided with two strings, s and t. The string t is constructed by shuffling s and appending exactly one new letter at a random position. Our objective is to identify this specific added character. While this may seem like a simple frequency counting problem, it serves as a classic introduction to bit manipulation techniques used in serious technical interviews.
Brute Force Approach for Find the Difference
A common initial approach to solving this problem involves sorting. Since t is a permutation of s with one extra element, sorting both strings aligns the identical characters.
- Sort string
salphabetically. - Sort string
talphabetically. - Iterate through the length of
s. Compare the character ats[i]witht[i]. - The first index where the characters differ indicates that
t[i]is the added character. - If the loop completes without finding a difference, the added character must be the last character of
t.
Pseudo-code:
function findDifference(s, t):
sort(s)
sort(t)
for i from 0 to length(s) - 1:
if s[i] != t[i]:
return t[i]
return t[last_index]Time Complexity Analysis: The time complexity is dominated by the sorting operation, which is , where is the length of the string.
Why it is suboptimal: While is acceptable for small constraints (), it is inefficient compared to linear time solutions. Sorting destroys the original order to establish a comparison, but we do not actually need the data to be ordered—we only need to determine identity. We can solve this in without the overhead of sorting algorithms.
Algorithm Strategy: Bit Manipulation Patterns
The strategy is to maintain a single running variable, often initialized to 0 (or the first element, depending on implementation preference). We iterate through both strings, applying the XOR operation between the running variable and the ASCII value of the current character.
- Initialization: Create a variable (e.g.,
result) initialized to 0. This acts as our accumulator. - Process String
s: Loop through each character ins, converting it to its integer representation, and updateresultusingresult ^= char_code. - Process String
t: Loop through each character int, doing the same. - Final State: Due to the cancellation property,
resultnow holds the integer value of the unique character. - Output: Convert
resultback to a character and return it.
This approach requires no auxiliary data structures like Hash Maps or Arrays, strictly adhering to space complexity.
Execution Flow
Let's trace the algorithm with s = "ab", t = "cba".
- Initialize:
result = 0(Binary00000000). - Process
s("ab"):- Current char: 'a' (ASCII 97).
result = 0 ^ 97 = 97. - Current char: 'b' (ASCII 98).
result = 97 ^ 98.
- Current char: 'a' (ASCII 97).
- Process
t("cba"):- Current char: 'c' (ASCII 99).
result = 97 ^ 98 ^ 99. - Current char: 'b' (ASCII 98).
result = 97 ^ 98 ^ 99 ^ 98. - Current char: 'a' (ASCII 97).
result = 97 ^ 98 ^ 99 ^ 98 ^ 97.
- Current char: 'c' (ASCII 99).
- Simplification (Mental Model):
- Rearrange terms (associativity):
(97 ^ 97) ^ (98 ^ 98) ^ 99. - Apply cancellation:
0 ^ 0 ^ 99. - Apply identity:
99.
- Rearrange terms (associativity):
- Result: The value 99 corresponds to the character 'c'.
Proof of Correctness
The correctness relies on the mathematical definition of the XOR field. Let be the set of characters in s and be the set of characters in t. We calculate:
Since where is the added character, the equation becomes:
Thus, the algorithm is mathematically guaranteed to return the added character.
Pattern Reuse Notes
The Bitwise XOR - Finding Single/Missing Number pattern is highly reusable. Understanding the cancellation property applies directly to these problems:
- LeetCode 136: Single Number - Identical logic: find the element appearing once in an array of duplicates.
- LeetCode 137: Single Number II - A variation where elements appear three times; requires more complex bit logic but follows the same principle.
- LeetCode 268: Missing Number - XORing the array indices against the values to find the missing index.
Feynman coach · Before you peek at the code
Can you explain the core insight in your own words?
If you can explain it before reading code, you’re far more likely to recall it under interview pressure.
Reference Implementation
C++ Solution for LeetCode 389
1class Solution {
2public:
3 char findTheDifference(string s, string t) {
4 char result = 0;
5
6 // XOR all characters in s
7 for (char c : s) {
8 result ^= c;
9 }
10
11 // XOR all characters in t
12 // Matching characters will cancel out
13 for (char c : t) {
14 result ^= c;
15 }
16
17 return result;
18 }
19};Java Solution for LeetCode 389
1class Solution {
2 public char findTheDifference(String s, String t) {
3 char result = 0;
4
5 // Iterate through s and XOR
6 for (int i = 0; i < s.length(); i++) {
7 result ^= s.charAt(i);
8 }
9
10 // Iterate through t and XOR
11 for (int i = 0; i < t.length(); i++) {
12 result ^= t.charAt(i);
13 }
14
15 return result;
16 }
17}Python Solution for LeetCode 389
1class Solution:
2 def findTheDifference(self, s: str, t: str) -> str:
3 result = 0
4
5 # In Python, we must convert char to int using ord()
6 for char in s:
7 result ^= ord(char)
8
9 for char in t:
10 result ^= ord(char)
11
12 # Convert the final integer back to a character
13 return chr(result)