题解:学而思编程 字符串

【题目来源】

学而思编程:字符串

【题目描述】

小猴最近学习了字符串,为了加强对字符串的理解,猴博士特意给小猴安排了一道编程题:

给定一个字符串 \(s\),保证 \(s\) 中只包含大写字母('A' - 'Z'),请你判断字符串 \(s\) 中是否包含了全部 \(26\) 个英文字母,无论某个英文字母是以大写还是小写形式出现在字符串中,均视为该字符串包含此字母。

现在请你帮助小猴完成这个编程题。

【输入】

一行,一个字符串 \(s\)

【输出】

一行,如果给定字符串包含了全部 \(26\) 个英文字母,则输出Yes,否则输出No。

【输入样例】

toosmallword

【输出样例】

No

【核心思想】

  1. 问题分析:给定一个字符串 \(s\),判断其是否包含全部 \(26\) 个英文字母(不区分大小写)。这是一个桶计数(Bucket Counting)问题,核心在于高效统计字符出现情况,忽略大小写差异。

  2. 算法选择

    • 统一大小写:将所有字符转换为同一种大小写形式,消除大小写差异
    • 桶数组(Bucket Array):利用布尔数组 \(f\) 标记每个字符是否出现,实现 \(O(1)\) 的字符存在性查询
  3. 关键步骤

    • 初始化:创建布尔数组 \(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
  4. 时间/空间复杂度

    • 时间复杂度:\(O(|s| + 26)\),遍历字符串 \(O(|s|)\),检查 \(26\) 个字母 \(O(26)\)
    • 空间复杂度:\(O(128)\),固定大小的 ASCII 码桶数组
  5. 桶计数的核心思想

    • 哈希思想的简化实现:利用字符的 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
posted @ 2026-07-06 21:03  团爸讲算法  阅读(7)  评论(0)    收藏  举报