如何高效统计字符串中各字母的出现次数?
更高效的字母出现次数统计方案
嘿,这个问题我太熟了!你现在写的一堆if分支确实有点繁琐,不仅代码冗余,扩展性也差——要是以后要区分大小写或者处理非英文字符,改起来简直头大。给你几个更优雅高效的实现思路:
方案一:用数组统计(性能最优)
英文字母总共26个,我们可以利用ASCII码的连续性来映射数组索引,这是性能最高的方案,时间复杂度为O(n)(n是字符串长度),每个字符只需要一次常数时间的访问。
如果需要忽略大小写,先把字符统一转成小写(或大写),再计算索引:
#include <iostream> #include <string> #include <cctype> // 提供tolower和isalpha函数 using namespace std; int main() { string str = "Example"; int count[26] = {0}; // 初始化所有统计位为0 // 用范围for循环遍历字符串,比传统下标循环更简洁 for (char c : str) { // 先过滤非字母字符(如果不需要过滤可以去掉这步) if (isalpha(c)) { char lower_c = tolower(c); // 计算当前字母对应的数组索引:'a'的ASCII是97,所以lower_c - 'a'会得到0-25的数值 count[lower_c - 'a']++; } } // 输出统计结果 for (int i = 0; i < 26; i++) { if (count[i] > 0) { cout << static_cast<char>('a' + i) << ": " << count[i] << endl; } } return 0; }
如果需要严格区分大小写,可以把数组扩容到52位(26个大写+26个小写),或者用两个数组分别统计:
// 区分大小写的版本 int upperCount[26] = {0}; int lowerCount[26] = {0}; for (char c : str) { if (isupper(c)) { upperCount[c - 'A']++; } else if (islower(c)) { lowerCount[c - 'a']++; } }
方案二:用哈希表(灵活通用)
如果你的字符串可能包含非英文字母(比如其他语言字符、符号),用C++标准库的unordered_map(哈希表)会更灵活。它的平均查找和插入时间都是O(1),比map的O(log n)性能更好:
#include <iostream> #include <string> #include <unordered_map> #include <cctype> using namespace std; int main() { string str = "Example"; unordered_map<char, int> charCount; for (char c : str) { if (isalpha(c)) { // 忽略大小写的话就统一转成小写 char lower_c = tolower(c); // 如果键不存在,unordered_map会自动初始化值为0,直接自增即可 charCount[lower_c]++; } } // 遍历哈希表输出结果 for (const auto& pair : charCount) { cout << pair.first << ": " << pair.second << endl; } return 0; }
这个方案不需要预先知道字符范围,能处理任意类型的字符,代码也更简洁,唯一的小缺点是哈希表的开销比数组略大,但对于绝大多数日常场景完全够用。
额外提示
- 如果不需要过滤非字母字符,直接去掉
isalpha的判断即可; - 范围for循环是C++11及以上支持的语法,如果你用的是老版本,换成传统的下标循环也完全没问题。
内容的提问来源于stack exchange,提问作者Skullruss
相关产品推荐
相关产品推荐

