Buddy Strings
Buddy Strings
The problem: Given two lowercase letter strings A and B, return true if you can swap two characters in A to make it equal to B, otherwise return false.
First Approach
Solve this directly from the definition. If swapping two characters in A makes it equal to B, then both strings must have the same character signature (same letters with same counts). There’s one edge case: when both strings are identical, A must contain duplicate letters to allow a valid swap.
Time complexity: O(n) Space complexity: O(1)
bool buddyStrings(string a, string b) {
// Lengths must be equal and non-empty
if (a.size() != b.size() || a.empty() || b.empty()) return false;
bool repeat = false;
int sign[26] = {0};
// Build signature of string A
for(auto s : a)
++sign[s-'a'];
for(auto s : b) {
// Check if A has duplicates
if (sign[s-'a'] > 1) repeat = true;
--sign[s-'a'];
}
// Check if A and B have same character signature
for(auto n : sign)
if (n!=0) return false;
// Signatures match, compare character by character
int i,j;
for(i=0;i<a.size() && a[i]==b[i];++i) {}
if (i==a.size()) return repeat; // Strings equal, depends on A having duplicate chars
// Strings differ, do one swap
for(j=i+1;a[j]!=b[i];++j) {}
swap(a[j], a[i]);
// After swap, check if strings match
for(;i<a.size() && a[i]==b[i];++i) {}
return i==a.size();
}Cleaner Way to Check Duplicates and Differences
Use unordered_set container to remove duplicates. Compare the container’s size() with the string length to detect duplicates.
bool buddyStrings(string A, string B) {
// Same length
int len_A = A.size(), len_B = B.size();
if (len_A != len_B) return false;
// Repeat: same string, A needs repeated char, like "aab" "aab"
int numChar_A = unordered_set<char>(A.begin(), A.end()).size();
// Handle duplicate case quickly
if (A == B && numChar_A < len_B) return true;
vector<int> index_diff;
for (int i = 0; i < len_A; i++) {
// diff records only different indices, count cannot exceed 2
if (A[i] != B[i]) index_diff.push_back(i);
if (index_diff.size() > 2) return false;
}
// Different indices count is 2 and corresponding letters cross-equal meet requirements
return index_diff.size() == 2 &&
A[index_diff[0]] == B[index_diff[1]] &&
A[index_diff[1]] == B[index_diff[0]];
}Key Insights
unordered_setfor quick deduplication- One pass through both strings to record different indices
#bucket #string #hashset