859. Buddy Strings*
https://leetcode.com/problems/buddy-strings/
题目描述
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.
C++ 实现 1
这道题的需要注意题目中描述的 if and only if
, 即 A
中的字符必须交换一次. 下面代码的思路是, 采用对撞指针, 找到 A[l] != B[l]
以及 A[r] != B[r]
, 并交换 std::swap(A[l], A[r])
, 使用 swap_time
记录交换的次数.
然而, 由于必须交换 1 次, 那么遇到 A = "aa", B = "aa"
这样的情况 (即 A
和 B
完全相等), 上面的思路就会出错. 因此需要对上面的思路进行修正. 观察发现, 如果 A
和 B
完全相等, 那么只要 A
中存在两个字符相等, 就可以交换这两个字符, 比如 A = "aba", B = "aba"
这个例子, 可以交换两个 a
; 而对于 A = "ab", B = "ab"
这个例子, 由于 A
中不存在两个相等的字符, 没法进行一次交换, 就需要返回 false
.
为了检测 A
中是否存在两个相同的字符, 使用哈希表记录 A
中的字符个数, 并用 max_num
记录字符最大的个数. 当 A
和 B
完全相等(此时 l > r && swap_time = 0
), 只有当 max_num > 1
时才返回 true
.
class Solution {
public:
bool buddyStrings(string A, string B) {
if (A.size() < 2 || B.size() < 2 || A.size() != B.size()) return false;
int l = 0, r = A.size() - 1;
int swap_time = 0, max_num = 0;
unordered_map<char, int> record;
while (l <= r) {
while (l <= r && A[l] == B[l]) {
record[A[l]] ++;
max_num = std::max(max_num, record[A[l]]);
++ l;
}
while (l <= r && A[r] == B[r]) {
record[A[r]] ++;
max_num = std::max(max_num, record[A[r]]);
-- r;
}
if (l > r) {
// 两序列完全相等, 但无相同字母
if ((swap_time == 0 && max_num < 2) || swap_time > 1) return false;
else return true;
}
std::swap(A[l], A[r]);
if (++swap_time > 1) return false;
}
if ((swap_time == 0 && max_num < 2) || swap_time > 1) return false;
else return true;
}
};
C++ 实现 2
来自 Easy Understood. 思路和 C++ 实现 1
一样, 但是更为清晰, 代码更为简洁.
If
A.length() != B.length()
: no possible swapIf
A == B
, we need swap two same characters. Check is duplicated char inA
.In other cases, we find index for
A[i] != B[i]
. There should be only 2 diffs and it’s our one swap.
class Solution {
public:
bool buddyStrings(string A, string B) {
if (A.length() != B.length()) return false;
if (A == B && set<char>(A.begin(), A.end()).size() < A.size()) return true;
vector<int> dif;
for (int i = 0; i < A.length(); ++i) if (A[i] != B[i]) dif.push_back(i);
return dif.size() == 2 && A[dif[0]] == B[dif[1]] && A[dif[1]] == B[dif[0]];
}
};