题目描述
给你长度相等的两个字符串 s1
和 s2
。一次 字符串交换 操作的步骤如下:选出某个字符串中的两个下标(不必不同),并交换这两个下标所对应的字符。
如果对 其中一个字符串 执行 最多一次字符串交换 就可以使两个字符串相等,返回 true
;否则,返回 false
。
样例
输入:s1 = "bank", s2 = "kanb"
输出:true
解释:例如,交换 s2 中的第一个和最后一个字符可以得到 "bank"。
输入:s1 = "attack", s2 = "defend"
输出:false
解释:一次字符串交换无法使两个字符串相等。
输入:s1 = "kelb", s2 = "kelb"
输出:true
解释:两个字符串已经相等,所以不需要进行字符串交换。
输入:s1 = "abcd", s2 = "dcba"
输出:false
限制
1 <= s1.length, s2.length <= 100
s1.length == s2.length
s1
和s2
仅由小写英文字母组成。
算法
(暴力枚举) $O(n)$
- 寻找两个字符串不同的位置。
- 如果不同的位置只有 1 个或者多于 2 个,则返回
false
。 - 如果没有不同的位置,则返回
true
。否则尝试交换两个不同的位置,判断是否可以使两个字符串相等。
时间复杂度
- 遍历两个字符串各一次,故总时间复杂度为 $O(n)$。
空间复杂度
- 仅需要常数的额外空间。
C++ 代码
class Solution {
public:
bool areAlmostEqual(string s1, string s2) {
const int n = s1.size();
int first = -1, second = -1;
for (int i = 0; i < n; i++) {
if (s1[i] == s2[i])
continue;
if (first == -1)
first = i;
else if (second == -1)
second = i;
else
return false;
}
if (first == -1)
return true;
if (first != -1 && second == -1)
return false;
return s1[first] == s2[second] && s1[second] == s2[first];
}
};