Easy
题目描述
如果两个字符串 word1 和 word2 中每个字母 ‘a’ 到 ‘z’ 的出现频次差值最多为 3,则认为这两个字符串几乎相等。
给定两个长度均为 n 的字符串 word1 和 word2,如果 word1 和 word2 几乎相等,则返回 true,否则返回 false。
字母 x 的频次是指它在字符串中出现的次数。
示例 1:
输入:word1 = "aaaa", word2 = "bccb"
输出:false
解释:"aaaa" 中有 4 个 'a',但 "bccb" 中有 0 个 'a'。
差值为 4,超过了允许的 3。
示例 2:
输入:word1 = "abcdeef", word2 = "abaaacc"
输出:true
解释:word1 和 word2 中每个字母频次的差值最多为 3:
- 'a' 在 word1 中出现 1 次,在 word2 中出现 4 次。差值为 3。
- 'b' 在 word1 中出现 1 次,在 word2 中出现 1 次。差值为 0。
- 'c' 在 word1 中出现 1 次,在 word2 中出现 2 次。差值为 1。
- 'd' 在 word1 中出现 1 次,在 word2 中出现 0 次。差值为 1。
- 'e' 在 word1 中出现 2 次,在 word2 中出现 0 次。差值为 2。
- 'f' 在 word1 中出现 1 次,在 word2 中出现 0 次。差值为 1。
示例 3:
输入:word1 = "cccddabba", word2 = "babababab"
输出:true
约束条件:
- n == word1.length == word2.length
- 1 <= n <= 100
- word1 和 word2 只包含小写英文字母
解题思路
解题思路
这道题的核心是统计两个字符串中每个字符的出现频次,然后比较对应字符频次的差值是否都不超过 3。
方法一:哈希表统计(推荐)
- 分别统计两个字符串中每个字符的出现频次
- 遍历所有可能的字符(‘a’ 到 ‘z’),计算每个字符在两个字符串中出现频次的绝对差值
- 如果任意字符的频次差值超过 3,返回 false;否则返回 true
方法二:数组计数优化
由于题目限定只有小写字母,可以使用长度为 26 的数组代替哈希表,通过 ch - 'a' 计算索引,空间效率更高。
方法三:单次遍历差值统计
可以在一次遍历中同时处理两个字符串,用一个数组记录字符频次差值,word1 中的字符 +1,word2 中的字符 -1,最后检查所有差值的绝对值是否都不超过 3。
时间复杂度主要是 O(n),其中 n 是字符串长度。由于需要检查固定的 26 个字母,常数项较小。
代码实现
class Solution {
public:
bool checkAlmostEquivalent(string word1, string word2) {
vector<int> count(26, 0);
// 统计频次差值:word1中的字符+1,word2中的字符-1
for (char c : word1) {
count[c - 'a']++;
}
for (char c : word2) {
count[c - 'a']--;
}
// 检查所有字符的频次差值是否都不超过3
for (int diff : count) {
if (abs(diff) > 3) {
return false;
}
}
return true;
}
};
class Solution:
def checkAlmostEquivalent(self, word1: str, word2: str) -> bool:
count = [0] * 26
# 统计频次差值:word1中的字符+1,word2中的字符-1
for c in word1:
count[ord(c) - ord('a')] += 1
for c in word2:
count[ord(c) - ord('a')] -= 1
# 检查所有字符的频次差值是否都不超过3
return all(abs(diff) <= 3 for diff in count)
public class Solution {
public bool CheckAlmostEquivalent(string word1, string word2) {
int[] count = new int[26];
// 统计频次差值:word1中的字符+1,word2中的字符-1
foreach (char c in word1) {
count[c - 'a']++;
}
foreach (char c in word2) {
count[c - 'a']--;
}
// 检查所有字符的频次差值是否都不超过3
foreach (int diff in count) {
if (Math.Abs(diff) > 3) {
return false;
}
}
return true;
}
}
var checkAlmostEquivalent = function(word1, word2) {
const count = new Array(26).fill(0);
// 统计频次差值:word1中的字符+1,word2中的字符-1
for (let c of word1) {
count[c.charCodeAt(0) - 97]++;
}
for (let c of word2) {
count[c.charCodeAt(0) - 97]--;
}
// 检查所有字符的频次差值是否都不超过3
return count.every(diff => Math.abs(diff) <= 3);
};
复杂度分析
| 复杂度类型 | 复杂度 | 说明 |
|---|---|---|
| 时间复杂度 | O(n) | n 是字符串长度,需要遍历两个字符串各一次 |
| 空间复杂度 | O(1) | 使用固定大小为 26 的数组,空间复杂度为常数 |