Easy
题目描述
给你两个字符串 s 和 goal ,只要我们可以通过交换 s 中的两个字母得到与 goal 相等的结果,就返回 true ;否则返回 false 。
交换字母的定义是:取两个下标 i 和 j (下标从 0 开始)且满足 i != j ,并交换 s[i] 和 s[j] 处的字符。
- 例如,在 “abcd” 中交换下标 0 和下标 2 的元素可以生成 “cbad” 。
示例 1:
输入:s = "ab", goal = "ba"
输出:true
解释:你可以交换 s[0] = 'a' 和 s[1] = 'b' 生成 "ba",此时 s 与 goal 相等。
示例 2:
输入:s = "ab", goal = "ab"
输出:false
解释:你只能交换 s[0] = 'a' 和 s[1] = 'b' 生成 "ba",此时 s 与 goal 不相等。
示例 3:
输入:s = "aa", goal = "aa"
输出:true
解释:你可以交换 s[0] = 'a' 和 s[1] = 'a' 生成 "aa",此时 s 与 goal 相等。
提示:
- 1 <= s.length, goal.length <= 2 * 10⁴
- s 和 goal 由小写英文字母组成
解题思路
这道题需要判断通过交换字符串 s 中的两个字符是否能得到 goal。我们需要分情况讨论:
核心思路:
- 首先检查两个字符串长度是否相等,不等则直接返回 false
- 找出所有不同位置的字符对
- 根据不同位置的数量进行分类处理
情况分析:
- 完全相同:如果 s 和 goal 完全相同,需要检查是否存在重复字符。如果有重复字符,可以交换这两个相同的字符;如果没有重复字符,则无法进行有效交换
- 恰好两处不同:检查这两处不同是否互为交换关系,即 s[i] == goal[j] && s[j] == goal[i]
- 其他情况:超过两处不同或只有一处不同,都无法通过一次交换达到目标
算法步骤:
- 遍历字符串,记录所有不同的位置
- 如果不同位置为0,检查是否有重复字符
- 如果不同位置为2,检查是否满足交换条件
- 其他情况返回 false
时间复杂度为 O(n),空间复杂度为 O(1)。
代码实现
class Solution {
public:
bool buddyStrings(string s, string goal) {
if (s.length() != goal.length()) {
return false;
}
vector<int> diff;
for (int i = 0; i < s.length(); i++) {
if (s[i] != goal[i]) {
diff.push_back(i);
}
}
if (diff.size() == 0) {
// 两个字符串相同,需要检查是否有重复字符
vector<int> count(26, 0);
for (char c : s) {
count[c - 'a']++;
if (count[c - 'a'] > 1) {
return true;
}
}
return false;
} else if (diff.size() == 2) {
// 恰好两处不同,检查是否可以交换
return s[diff[0]] == goal[diff[1]] && s[diff[1]] == goal[diff[0]];
}
return false;
}
};
class Solution:
def buddyStrings(self, s: str, goal: str) -> bool:
if len(s) != len(goal):
return False
diff = []
for i in range(len(s)):
if s[i] != goal[i]:
diff.append(i)
if len(diff) == 0:
# 两个字符串相同,需要检查是否有重复字符
return len(set(s)) < len(s)
elif len(diff) == 2:
# 恰好两处不同,检查是否可以交换
return s[diff[0]] == goal[diff[1]] and s[diff[1]] == goal[diff[0]]
return False
public class Solution {
public bool BuddyStrings(string s, string goal) {
if (s.Length != goal.Length) {
return false;
}
List<int> diff = new List<int>();
for (int i = 0; i < s.Length; i++) {
if (s[i] != goal[i]) {
diff.Add(i);
}
}
if (diff.Count == 0) {
// 两个字符串相同,需要检查是否有重复字符
int[] count = new int[26];
foreach (char c in s) {
count[c - 'a']++;
if (count[c - 'a'] > 1) {
return true;
}
}
return false;
} else if (diff.Count == 2) {
// 恰好两处不同,检查是否可以交换
return s[diff[0]] == goal[diff[1]] && s[diff[1]] == goal[diff[0]];
}
return false;
}
}
var buddyStrings = function(s, goal) {
if (s.length !== goal.length) return false;
if (s === goal) {
const charCount = new Set(s);
return charCount.size < s.length;
}
const diff = [];
for (let i = 0; i < s.length; i++) {
if (s[i] !== goal[i]) {
diff.push(i);
}
}
return diff.length === 2 && s[diff[0]] === goal[diff[1]] && s[diff[1]] === goal[diff[0]];
};
复杂度分析
| 复杂度类型 | 复杂度 | 说明 |
|---|---|---|
| 时间复杂度 | O(n) | 需要遍历整个字符串一次,n为字符串长度 |
| 空间复杂度 | O(1) | 只使用常数额外空间存储不同位置和字符计数 |