题解:学而思编程 字符串
【题目来源】
学而思编程:字符串
【题目描述】
小猴最近学习了字符串,为了加强对字符串的理解,猴博士特意给小猴安排了一道编程题:
给定一个字符串 \(s\),保证 \(s\) 中只包含大写字母('A' - 'Z'),请你判断字符串 \(s\) 中是否包含了全部 \(26\) 个英文字母,无论某个英文字母是以大写还是小写形式出现在字符串中,均视为该字符串包含此字母。
现在请你帮助小猴完成这个编程题。
【输入】
一行,一个字符串 \(s\)。
【输出】
一行,如果给定字符串包含了全部 \(26\) 个英文字母,则输出Yes,否则输出No。
【输入样例】
toosmallword
【输出样例】
No
【核心思想】
-
问题分析:给定一个字符串 \(s\),判断其是否包含全部 \(26\) 个英文字母(不区分大小写)。这是一个桶计数(Bucket Counting)问题,核心在于高效统计字符出现情况,忽略大小写差异。
-
算法选择:
- 统一大小写:将所有字符转换为同一种大小写形式,消除大小写差异
- 桶数组(Bucket Array):利用布尔数组 \(f\) 标记每个字符是否出现,实现 \(O(1)\) 的字符存在性查询
-
关键步骤:
- 初始化:创建布尔数组 \(f[0..129]\),初始值为 \(false\)
- 遍历字符串(处理每个字符 \(s_i\)):
- 若 \(s_i \in ['A', 'Z']\):\(s_i \leftarrow s_i - 'A' + 'a'\),转换为大写转小写
- 标记出现:\(f[s_i] \leftarrow true\)
- 检查完整性:遍历 \(i\) 从 \('a'\) 到 \('z'\),若存在 \(f[i] = false\),输出
No并结束 - 输出结果:若 \(26\) 个字母均出现,输出
Yes
-
时间/空间复杂度:
- 时间复杂度:\(O(|s| + 26)\),遍历字符串 \(O(|s|)\),检查 \(26\) 个字母 \(O(26)\)
- 空间复杂度:\(O(128)\),固定大小的 ASCII 码桶数组
-
桶计数的核心思想:
- 哈希思想的简化实现:利用字符的 ASCII 码值作为数组下标,将字符映射到固定位置,实现 \(O(1)\) 的标记和查询
- 大小写归一化:通过统一转换为小写(或大写),将 \(52\) 个可能字符压缩为 \(26\) 个有效状态,简化统计逻辑
- 布尔标记替代计数:只需知道字符是否出现,无需统计出现次数,使用 \(bool\) 类型即可满足需求,空间更优
- 提前终止优化:一旦发现某个字母缺失立即输出结果,避免不必要的完整遍历
- 适用于字符集有限、需要快速判断元素存在性的统计类问题
【解题思路】

【算法标签】
字符串入门
【代码详解】
#include <bits/stdc++.h>
using namespace std;
bool f[130]; // 直接按照ASCII码定义数组
int main()
{
string s;
cin >> s;
// 统一成小写,统计每个字母是否出现
for (int i=0; i<s.size(); i++) {
if (s[i]>='A' && s[i]<='Z') {
s[i] = s[i] - 'A' + 'a';
}
f[s[i]] = true; // 使用桶记录每个字符
}
for (int i='a'; i<='z'; i++) { // 遍历26个字母的下标
if (!f[i]) { // 如果其中有f[i]==false
cout << "No" << endl; // 输出No
return 0;
}
}
cout << "Yes" << endl; // 如果可以遍历完,则输出Yes
return 0;
}
【运行结果】
toosmallword
No
浙公网安备 33010602011771号