859. Buddy Strings
859. Buddy Strings
原题:两个小写字母组成的字符串当且仅当串 A 交换两个字符与串 B 相等的时候返回 true 否则返回 false
第一次解法
根据题意直白来解,如果仅仅是交换字符能相等的话那么两个字符的哈希签名必须相等,还有一个 corner case 是两个串相等的时候 A 中必须要有重复的字母才能成立
时间复杂度:O(n) 空间复杂度:O(1)
bool buddyStrings(string a, string b) {
// 长度必须相等且不为空
if (a.size()!=b.size() || a.empty() || b.empty()) return false;
bool repeat = false;
int sign[26] = {0};
// 构造 A 串的签名
for(auto s : a)
++sign[s-'a'];
for(auto s : b) {
// 检查A串是否有重复
if (sign[s-'a'] > 1) repeat = true;
--sign[s-'a'];
}
// 检查 A 与 B 的字符签名是否一致
for(auto n : sign)
if (n!=0) return false;
// 签名一致则从头开始逐一比对
int i,j;
for(i=0;i<a.size() && a[i]==b[i];++i) {}
if (i==a.size()) return repeat; // 串相等,取决于A是否有重复字符
// 串不等,进行一次交换
for(j=i+1;a[j]!=b[i];++j) {}
swap(a[j], a[i]);
// 交换后继续逐一比对得结果
for(;i<a.size() && a[i]==b[i];++i) {}
return i==a.size();
}更简洁的方式判断重复与 diff
通过使用 stl 中的 unordered_set 容器来去重,根据容器的 size() 和B串的长度来判断是否重复
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();
// 快速解决掉重复的情况
if (A == B && numChar_A < len_B) return true;
vector<int> index_diff;
for (int i = 0; i < len_A; i++) {
// diff 仅记录不一样的下标,个数不能超过2个
if (A[i] != B[i]) index_diff.push_back(i);
if (index_diff.size() > 2) return false;
}
// 不一样的下标个数为2且对应字母交叉相等则符合要求
return index_diff.size() == 2 &&
A[index_diff[0]] == B[index_diff[1]] &&
A[index_diff[1]] == B[index_diff[0]];
}收获
unordered_set快速去重- diff 遍历一遍记录不同的下标
#桶 #字符串 #HashSet