做题笔记:字符串相似对的计数
问题分析
本题给定了一组字符串,我们需要统计其中有多少对字符串是相似的。根据题意,两个字符串相似当且仅当它们的每个字母出现的次数完全相同。换句话说,两个字符串的字符频率是一样的,只是字符的顺序可能不同。
例如:
- "abcbd" 和 "dbcba" 是相似的,因为它们的字符频率分别为:
a:1, b:2, c:1, d:1
。 - "abb" 和 "aab" 不相似,因为它们的字符频率不同。
通过该题,我们可以将每个字符串转化为一个字符频率的表示,再比较这些频率是否相同。对于一组字符串中相似字符串对的统计,最直接的做法是将所有字符串的字符频率计算出来,然后统计频率相同的字符串对数。
解题思路
- 字符频率的表示:我们可以将每个字符串的字符频率表示为一个字符串。由于题目中的字符串仅包含小写字母,因此我们可以为每个字符串创建一个长度为26的数组(代表26个小写字母的频率)。将每个字母的频率填入对应的位置,最后将这个数组转化为字符串,作为这个字符串的"特征值"或"键"。
- 频率统计:我们需要统计每个频率字符串出现的次数。对于每个字符串,使用字符频率数组生成的"特征值"作为键,将其在一个哈希表中出现的次数进行统计。
- 计算相似字符串对数 :一旦我们得到每种字符频率字符串的出现次数,就可以根据组合数公式计算相似字符串对的数量。如果某种字符频率的字符串出现了
count
次,那么相似的字符串对数为count * (count - 1) / 2
,这是从count
个字符串中选取两个字符串的组合数。 - 最终输出结果:累加所有频率字符串的相似对数,即为最终结果。
代码实现
java
import java.util.HashMap;
import java.util.Map;
public class Solution {
public static int solution(int n, String[] strings) {
Map<String, Integer> frequencyMap = new HashMap<>();
// 统计每个字符串的字符频率
for (String str : strings) {
int[] charCount = new int[26]; // 26个字母的频率数组
for (char c : str.toCharArray()) {
charCount[c - 'a']++;
}
// 生成频率字符串
StringBuilder frequencyKey = new StringBuilder();
for (int count : charCount) {
frequencyKey.append(count).append('#'); // 用 '#' 分隔不同字符的频率
}
frequencyMap.put(frequencyKey.toString(), frequencyMap.getOrDefault(frequencyKey.toString(), 0) + 1);
}
// 计算相似字符串对的数量
int similarPairs = 0;
for (int count : frequencyMap.values()) {
if (count > 1) {
similarPairs += (count * (count - 1)) / 2; // 组合数
}
}
return similarPairs;
}
}
代码解析
frequencyMap
:这是一个哈希表,键为字符串的字符频率表示(即频率字符串),值为该频率字符串出现的次数。- 字符频率统计 :对于每个字符串,我们使用一个长度为26的数组
charCount
来记录字符串中每个字母的出现次数。然后,使用一个StringBuilder
将这些频率转化为一个字符串,并将该字符串作为键存入哈希表。 - 计算相似对数 :通过遍历哈希表中的每个键,计算该键对应的频率字符串出现的次数
count
,如果count
大于1,则可以从这些字符串中选择两两组合的方式计算相似对数,即使用组合数公式count * (count - 1) / 2
。 - 返回结果:最后返回所有相似字符串对的总数。
时间复杂度分析
- 字符频率计算 :对于每个字符串,我们需要遍历它的字符并更新字符频率。每个字符串的长度为
L
,总共有n
个字符串,因此字符频率计算的时间复杂度是O(n * L)
。 - 哈希表更新 :对于每个字符串,更新哈希表中的频率字符串的时间复杂度是常数时间
O(1)
,因此总的哈希表更新时间复杂度是O(n)
。 - 计算相似对数 :遍历哈希表中的所有频率字符串,最坏情况下我们可能会有
n
个不同的频率字符串,因此时间复杂度是O(n)
。
综上所述,整体的时间复杂度是 O(n * L)
,其中 n
是字符串的个数,L
是字符串的最大长度。
代码测试
考虑几个测试样例:
-
样例1:输入
n = 7, strings = ["abcbd", "dbcba", "abcd", "abcd", "adbc", "aa", "aa"]
,输出5
。- 字符频率统计:{"a:1, b:2, c:1, d:1": 2, "a:1, b:1, c:1, d:1": 1, "a:2": 2}
- 相似对数为 5。
-
样例2:输入
n = 3, strings = ["aab", "bba", "baa"]
,输出1
。- 字符频率统计:{"a:2, b:1": 3}
- 相似对数为 1。
-
样例3:输入
n = 5, strings = ["abc", "def", "ghi", "jkl", "mno"]
,输出0
。- 字符频率统计:所有字符频率都是唯一的,无相似对。