🔍 2025蓝桥杯备赛Day2 | 高频考点题解:第一个仅出现一次的字符(两种解法)
🚀 题目速览
题目难度:⭐️ 适合编程新手快速掌握字符串处理技巧
考察重点:字符串遍历、哈希表应用、时间空间复杂度优化
B2110 找第一个只出现一次的字符
题目描述
给定一个只包含小写字母的字符串,请你找到第一个仅出现一次的字符。如果没有,输出 no
。
输入格式
一个字符串,长度小于 1100 1100 1100。
输出格式
输出第一个仅出现一次的字符,若没有则输出 no
。
输入输出样例 #1
输入 #1
abcabd
输出 #1
c
输入输出样例 #2
输入 #2
aabbcc
输出 #2
no
🔥 解法一:数组映射法(最优解)
🛠️ 实现思路
核心技巧:利用ASCII码特性建立字符到数组索引的映射 算法优势:时间复杂度O(n),空间复杂度O(1)
#include <iostream>
#include <string>
using namespace std;
int main() {
string s;
cin >> s;
int count[26] = {0}; // 创建字母频次直方图
// 频次统计(核心操作)
for (char c : s) {
count[c - 'a']++; // 字符映射:'a'→0,'b'→1...
}
// 顺序查找首个唯一字符
for (char c : s) {
if (count[c - 'a'] == 1) {
cout << c << endl;
return 0; // 提前退出优化
}
}
cout << "no" << endl;
return 0;
}
💡 关键知识点
- ASCII映射技巧:
c - 'a'
将字符转换为0-25的整数索引 - 两次遍历策略:统计与查找分离,保证时间复杂度线性增长
- 空间优化:固定长度数组替代哈希表,减少内存开销
🌐 解法二:哈希表法(可扩展方案)
🛠️ 实现思路
适用场景:字符集范围不确定时(如含大小写/特殊字符) 扩展优势:代码逻辑更通用,便于后续题型变种
#include <iostream>
#include <unordered_map>
using namespace std;
string firstUniqueChar(const string& s) {
if (s.empty()) return "no"; // 边界条件处理
unordered_map<char, int> charCount;
// 建立字符频次字典
for (char ch : s) {
charCount[ch]++; // 自动处理新字符
}
// 顺序扫描找首个唯一字符
for (char ch : s) {
if (charCount[ch] == 1) {
return string(1, ch); // 转换为字符串输出
}
}
return "no";
}
int main() {
string s;
cin >> s;
cout << firstUniqueChar(s) << endl;
return 0;
}
💡 关键知识点
- 哈希表特性:自动处理未知字符,查询复杂度O(1)
- 鲁棒性设计:显式处理空字符串等边界情况
- 函数封装:提升代码可维护性和复用性
📊 方案对比分析
维度 | 数组法 | 哈希表法 |
---|---|---|
时间复杂度 | O(n) | O(n) |
空间复杂度 | O(1)(固定26元素) | O(1)(最多26键值对) |
扩展性 | 仅限已知字符集 | 支持任意ASCII/Unicode |
内存效率 | 更高(连续内存存储) | 略低(哈希表开销) |
代码简洁度 | ★★★★☆ | ★★★☆☆ |
🚦 实战技巧
- 输入预处理:题目虽说明是小写字母,但实际竞赛中建议添加合法性检查
- 提前返回优化:找到目标后立即return,减少不必要的遍历
- 内存预分配:数组法初始化时直接指定大小,避免动态扩容开销
🌟 举一反三
变种题思考:如果题目要求考虑大小写敏感的情况(如’a’和’A’算不同字符),应如何修改代码?
解法升级:只需调整字符处理逻辑:
// 在哈希表解法中移除字符过滤
for (char ch : s) {
charCount[ch]++; // 直接统计所有字符
}
蓝桥杯备赛小贴士:字符串处理类题目在竞赛中占比约15%,掌握高效的字符统计方法能显著提升解题速度!建议将数组映射法作为默认方案,遇到特殊字符处理需求时再切换哈希表方案。
👉 思考题:如果题目改为找出所有出现次数为奇数的字符,该如何修改算法?欢迎在评论区留下你的解法!