Buddy Strings, by LeetCode
Problem is here: https://leetcode.com/problems/buddy-strings/description/
Problem is deceivingly more obnoxious than it looks. Not hard in terms of "algorithms", but rather the different "special" cases need to be thought thru properly. Here they are:
Given two strings
A
and B
of lowercase letters, return true
if and only if we can swap two letters in A
so that the result equals B
.
Example 1:
Input: A = "ab", B = "ba" Output: true
Example 2:
Input: A = "ab", B = "ab" Output: false
Example 3:
Input: A = "aa", B = "aa" Output: true
Example 4:
Input: A = "aaaaaaabc", B = "aaaaaaacb" Output: true
Example 5:
Input: A = "", B = "aa" Output: false
Note:
0 <= A.length <= 20000
0 <= B.length <= 20000
A
andB
consist only of lowercase letters.
Problem is deceivingly more obnoxious than it looks. Not hard in terms of "algorithms", but rather the different "special" cases need to be thought thru properly. Here they are:
- Conditions where you know there won't be a solution:
- String have different lengths, OR
- At least one of them is null or empty, OR
- They are equal with unique characters only, OR
- They differ by more or less than 2 characters
- If the above passes, the next step is to check:
- If they are equal but at least one character is duplicated, then return true (the dupe chars can be swapped)
- If they differ by two characters, make sure that swapping them makes the strings equal
The code is a little more concise than the explanation above (below).
The interesting thing to notice here is that sometimes in real life problems, they are actually more like this nature where you're dealing mostly with the "special cases", trying to cover all the logical bases, rather than dealing with complex algorithms. Hope you enjoy, cheers, Marcelo
The interesting thing to notice here is that sometimes in real life problems, they are actually more like this nature where you're dealing mostly with the "special cases", trying to cover all the logical bases, rather than dealing with complex algorithms. Hope you enjoy, cheers, Marcelo
public class Solution { private bool OneDupe(string s) { Hashtable count = new Hashtable(); for (int i = 0; i < s.Length; i++) { char c = s[i]; if (!count.ContainsKey(c)) count.Add(c, 0); count[c] = (int)count[c] + 1; if ((int)count[c] > 1) return true; } return false; } public bool BuddyStrings(string A, string B) { if (String.IsNullOrEmpty(A) || String.IsNullOrEmpty(B)) return false; if (A.Length != B.Length) return false; if (A.Equals(B)) return OneDupe(A); int indexDiff1 = -1; int indexDiff2 = -1; int countDiff = 0; for (int i = 0; i < A.Length; i++) { if (A[i] != B[i]) { countDiff++; if (countDiff == 1) indexDiff1 = i; else if (countDiff == 2) indexDiff2 = i; else return false; } } return countDiff == 2 && A[indexDiff1] == B[indexDiff2] && A[indexDiff2] == B[indexDiff1]; } }
Very nice, Marcelo! My solution is extremely similar with an exception that it does not have an extra scan for the equality (though it does not affect asymptotic complexity), uses a vector instead of 2 variables and since it's written in C++ it runs in 4ms :)
ReplyDeleteclass Solution {
public:
bool buddyStrings(const string& A, const string& B) {
if (A.size() != B.size()) return false;
vector mismatches;
bool has_duplicates = false;
int letters = 0;
for (int i = 0; i < A.size(); ++i) {
int idx = 1 << (A[i] - 'a');
has_duplicates |= letters & idx;
letters |= idx;
if (A[i] != B[i]) {
if (mismatches.size() >= 2) return false;
mismatches.push_back(i);
}
}
if (mismatches.empty() && has_duplicates) return true;
if (mismatches.size() < 2 || mismatches.size() > 2) return false;
return A[mismatches[0]] == B[mismatches[1]] && A[mismatches[1]] == B[mismatches[0]];
}
};
https://gist.github.com/ttsugriy/ef261e21dc6ce2d5df6278aa1731af51