华为OD机考统计字符题满分攻略:从分类规则到边界避坑

发布时间:2026/9/17 7:05:20
华为OD机考统计字符题满分攻略:从分类规则到边界避坑 华为OD机考的题库里“统计字符”这类题看起来是最人畜无害的一种。没有复杂的算法没有绕人的数据结构很多人扫一眼就开始写循环结果在样例通过之后反复提交卡在90%的通过率上怎么都找不到漏掉的那个用例。我见过好几个准备华为OD机考的候选人不是死在难题上而是死在这种看似简单的送分题上。原因也很统一字符分类规则没想清楚、特殊字符没覆盖、输入读取方式踩了坑、输出格式和题目要求不完全一致。这篇文章就把“统计字符”这一类题彻底拆开从题目考察点、解题思路、多语言实现到机考现场的各种细节一次性讲透。这个话题适合正在准备华为OD机考、华为AI岗机考或者其他大厂在线笔试的开发者也适合刚接触算法题、想系统练习字符串基本功的新手。内容不绕弯子直接围绕这类题怎么拿满分展开代码可以直接抄思路和避坑点也能迁移到其他字符串题目上。1. 华为机考为什么要出“统计字符”这种基础题1.1 基础题才是真正筛人的题华为机考的题目一般分为三个梯度简单题保底、中等题拉分、难题区分高手。“统计字符”往往就是第一梯队的保底题但它承担的任务并不比难题轻。机考的核心目标是筛掉两类人一类是完全不会写代码的另一类是基础不牢、一写就漏的。统计字符这道题的价值在于它几乎覆盖了笔试中最容易被扣分的全部基础点输入字符串的读取方式、循环遍历的边界条件、字符分类的判断规则、计数变量的初始化、输出格式的精确匹配。任何一个环节没有养成肌肉记忆都会在某个隐藏用例上翻车。而且这类题往往占整套题的第一题一旦第一题没拿到满分后面做题的心态会肉眼可见地崩直接影响中等题和难题的发挥。1.2 常见的“统计字符”变体有哪些虽然题目都叫“统计字符”但翻看华为OD机考和其他大厂笔试的真实题库具体问法至少有四种每种问法的解题思路侧重点完全不同。题型变体典型描述核心考察点分类统计输入一行字符分别统计英文字母、数字、空格、其他字符的个数字符分类规则、多分支判断词频统计统计字符串中每个字符出现的次数哈希计数、遍历顺序删除最少字符删除字符串中出现次数最少的字符若多个字符出现次数相同且最少则一并删除频次统计、二次遍历、保留原序字典序输出按ASCII码升序或字符出现次数排序后输出排序规则、哈希表的遍历时机很多人准备的“统计字符”就是第一种但上了考场才发现问的是第三种或第四种。所以这篇文章我会把四种变体都覆盖到其中第一种和第三种会给出完整的代码实现因为这两类出现频率最高也是“统计字符”这个概念下最值得深挖的两种考法。2. 动手写循环之前先把字符分类规则定下来2.1 字符分类的三条技术路线统计字母、数字、空格、其他字符这四类时判断逻辑听起来很简单遍历字符串对每个字符进行分类。但“分类”这两个字里藏着这道题一半的坑。常见的字符分类方式有以下三种。第一种是直接用库函数判断。C里有isalpha()、isdigit()、isspace()Java里有Character.isLetter()、Character.isDigit()、Character.isWhitespace()Python里则有str.isalpha()、str.isdigit()、str.isspace()。这些函数语义清晰逻辑简短是多数人写这道题的第一选择。第二种是用ASCII码范围判断。英文字母的范围是A~Z和a~z数字是0~9空格是 ASCII码32。用比较运算手写判断不依赖任何语言内置函数。第三种是正则表达式匹配。比如用re.match(r[a-zA-Z], ch)判断字母。这种写法在在线笔试里不是首选因为正则匹配的耗时明显高于前两者而且可读性并没有好到哪里去。我个人的建议是C选手优先用ASCII码范围判断Java选手优先用Character系列方法Python选手优先用str系列方法。原因后面代码部分会细说核心思路是C里isalpha()的入参是int类型如果传入带符号的char在某些编译器上对扩展ASCII码会出问题Java和Python的内置字符函数则相对安全直接用即可。2.2 空格和空白字符是最大的边界陷阱“统计空格”和“统计空白字符”是两回事。空格单指 也就是ASCII码32而isspace()、Character.isWhitespace()这类函数把换行符\n、制表符\t、回车符\r都算作空白字符。如果题目明确说的是“空格”就应该只统计 。你要是用了isspace()遇到输入里夹着制表符的用例统计结果就会多算。反过来如果题目说的是“空白字符”你却只判了空格同样会漏算。这里有一个我在真实机考中踩过的细节题目输入一行字符这行字符里可能包含前导空格、连续空格甚至只有空格。很多人在自测时用“Hello World”这种正常字符串不会暴露问题但机考的隐藏用例往往极端。所以拿到题第一步是仔细读题目对“空格”的定义别想当然。3. 经典统计题的三语言实现与选型理由3.1 题目原型输入一行字符分别统计出其中英文字母、数字、空格和其他字符的个数。输出顺序为字母个数、数字个数、空格个数、其他字符个数。这是一个标准的“分类统计”题。下面给出C、Java、Python三版实现。3.2 C版本#include iostream #include string using namespace std; int main() { string s; getline(cin, s); int letter 0, digit 0, space 0, other 0; for (char c : s) { if ((c a c z) || (c A c Z)) { letter; } else if (c 0 c 9) { digit; } else if (c ) { space; } else { other; } } cout letter digit space other endl; return 0; }C版本里有两个关键点。第一是输入必须用getline(cin, s)而不是cin s。cin s遇到空格就会停止读取如果输入是Hello World 123它只会读到Hello后面的全丢了。统计字符题目的输入几乎必然包含空格所以getline是这道题在C里的必然选择。第二是字符判断用ASCII码范围而不是cctype里的isalpha。原因前面提过isalpha的入参是int如果char变量在平台上是有符号类型遇到ASCII码大于127的字符时传入isalpha会变成负数产生未定义行为。虽然统计英文字母的常规用例不会触发这个问题但机考的边界用例经常会放一些特殊字符进去安全起见不碰这个坑。3.3 Java版本import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner sc new Scanner(System.in); String s sc.nextLine(); int letter 0, digit 0, space 0, other 0; for (int i 0; i s.length(); i) { char c s.charAt(i); if (Character.isLetter(c)) { letter; } else if (Character.isDigit(c)) { digit; } else if (c ) { space; } else { other; } } System.out.println(letter digit space other); } }Java版用Character.isLetter()和Character.isDigit()是安全的。这里需要提醒一个不同点Character.isLetter()判断的是Unicode字母中文字符也会被判定为true。如果题目说的“英文字母”明确限定A-Z和a-z那就要像C版那样手写ASCII范围判断。华为机考这类题目中命题人要么只放英文字母进去测试要么就明确写了“英文字母”所以要仔细读题。如果题目写的是“英文字母”我的建议是无论用什么语言都用手写ASCII范围的方式从根源上避免歧义。输入读取用sc.nextLine()而不是sc.next()理由和C的getline完全一样。3.4 Python版本s input() letter digit space other 0 for ch in s: if ch.isalpha(): letter 1 elif ch.isdigit(): digit 1 elif ch : space 1 else: other 1 print(letter, digit, space, other)Python的input()直接读取整行天然支持空格。str.isalpha()同样有中文判断为True的问题如果题目限定英文字母就用(a ch z) or (A ch Z)代替。Python版本的print(letter, digit, space, other)会自动用空格隔开输出格式恰好就是题目要求的“数字之间用一个空格分隔”。这时候不必画蛇添足去搞字符串拼接。3.5 三语言选型的核心判断标准这三版实现背后的选型逻辑其实是同一个原则最低风险地完成题目要求。C选手不依赖库函数是因为C字符库函数在某些边缘情况有坑Java和Python选手优先用库函数是因为这两个语言的字符API语义稳定日常开发中已经被验证过无数次。而如果题目对“字母”的限定是英文则所有语言都退回ASCII范围手写判断因为只有这样能精确匹配题目语义。在线笔试的评分只看用例通过率不喜欢在不稳定的API行为上赌输赢。凡是语言层面有歧义的地方一律用手写判断绕过去。4. 高频变体“删除最少出现字符”的完整拆解4.1 题目原型实现删除字符串中出现次数最少的字符若多个字符出现次数相同且同为最少则一并删除。输出删除这些单词后的字符串字符串中其它字符保持原来的顺序。这是华为OD机考中反复出现的经典题本质还是“统计字符”。第一眼看上去它比单纯的四分类统计多了一层逻辑但拆开之后就是三个固定步骤统计频次、找到最小频次、按原序输出过滤后的字符。每一个步骤都不难但把它们串起来的时候很容易在第二步和第三步之间翻车。4.2 完整代码实现Pythons input() # 第一步统计每个字符出现的次数 count {} for ch in s: count[ch] count.get(ch, 0) 1 # 第二步找到最小出现次数 min_count min(count.values()) # 第三步按原序输出出现次数大于最小次数的字符 result [] for ch in s: if count[ch] min_count: result.append(ch) print(.join(result))这个实现只有不到十行核心代码但每一步都有值得展开的细节。4.3 第一遍遍历统计频次的正确姿势统计频次用的是哈希表Python里的dict。count[ch] count.get(ch, 0) 1这个写法相当于一个通用套路如果字符第一次出现初始值为0再加1如果已经出现过就取当前值再加1。这里有个细节容易被忽略统计完成后哈希表的键就是字符串中出现过的所有字符值就是每个字符的出现次数。min(count.values())拿到的是最小频次的数值不是字符本身。为什么要拿数值而不是直接找字符因为可能有好几个字符共享同一个最小频次它们必须全部被删除。如果只删了一个字符答案就错了。4.4 二次遍历保持原序的做法第三步不能再遍历哈希表因为哈希表的遍历顺序和字符串中字符的出现顺序没有任何保证。必须重新遍历原始字符串对每个字符查一次哈希表判断它的出现次数是否大于最小频次。大于则保留等于则删除。这个设计是整道题的核心思想统计阶段用哈希表完成输出阶段用原始字符串完成。两个阶段各司其职统计阶段解决“哪些字符要删”的问题输出阶段解决“按照什么顺序输出”的问题。4.5 我踩过的输出坑这道题我最早写过一版“优雅”的代码遍历哈希表把最小频次对应的字符收集到一个集合里然后遍历原字符串如果字符在集合里就跳过。逻辑看起来没毛病但自测样例“aabbcc”时发现输出变成了空字符串因为a、b、c三个字符的出现次数都是2全部被删除了输出为空。这里其实是对的。真正出问题的是另一个用例输入“aaabbbcccdd”a、b、c各出现3次d出现2次应该只删除d输出“aaabbbccc”。我的第一版代码在收集要删除的字符时误用了“频次等于最小频次的字符”这一逻辑但遍历哈希表时哈希表的键顺序把d排在了中间导致我只测试了一个不含d的用例没暴露问题。所以后来我学乖了涉及“删除字符”的题目要删除的字符集合必须用频次数值计算出来并且要完整收集之后再用原字符串过滤不能图省事。5. 机考现场最容易翻车的五个操作细节这一部分没有代码全部是实战中总结的注意事项优先级和重要性不亚于算法本身。很多候选人不是不会做题而是输在了这些细节上。5.1 输入读取方式决定成败统计字符类的题目输入一行字符串字符串里几乎一定有空格。C用getline(cin, s)Java用sc.nextLine()Python用input()。这三者是标准答案。但如果你平时刷题习惯用C语言的scanf(%s, str)或者Java里习惯用sc.next()遇到这类题就会读不全输入。更隐蔽的情况是多组输入和单组输入的差异。有些题目说“输入一行”有些题目没有明确说只有一组为了稳妥可以在本地测试时重点验证带空格的样例。一个判断技巧题目描述里用的是“一行字符”还是“字符串”。如果是“一行字符”基本等价于包含空格的整行输入如果只说“字符串”有可能不含空格但保险起见也要按整行处理。5.2 循环结束后别忘了“尾巴”这个坑在变体题中更常见。比如有一些统计题会要求统计连续相同字符的个数这类题的思路是遍历字符串遇到字符变化时结算上一段的计数。很多人在字符串遍历结束后忘记处理最后一段导致最后一个连续段的统计结果丢失。“统计字符”的四种变体里如果出题人把题目改成“统计每个连续字符段的长度”那就必须记住循环结束后还需要再执行一次结算逻辑。这个细节虽然不直接出现在经典统计题里但同样是“遍历自然结束后的收尾”这一类基本功值得养成习惯。5.3 自测用例清单机考提交前我习惯在本地构建这样一组用例专门用来测试统计类题目的边界。建议你也直接拿去用。用例输入期望输出普通用例Hello World 123字母10、数字3、空格2、其他0全空格字母0、数字0、空格3、其他0空行直接回车字母0、数字0、空格0、其他0特殊符号HelloWorld#123!字母10、数字3、空格0、其他3无空格abc123字母3、数字3、空格0、其他0其中“空行”这个用例最容易被忽略。输入直接回车时getline、nextLine、input()都能读到空字符串循环体一次都不执行四个计数器全部为0输出“0 0 0 0”。很多人在这一步输出错误说明代码在空输入时没有正确处理。“全空格”用例也很关键。如果题目要求统计空格全空格的输入就会测试出空格计数逻辑是否正确。有些人用默认的split()预处理字符串时会把全空格输入当成空数组导致整个统计逻辑失效。5.4 时间复杂度和空间复杂度的快速估算华为机考通常会限制时间但统计字符这类题的数据规模一般不会特别大。即使字符串长度是10的6次方单次遍历的时间复杂度是O(n)任何现代编程语言都毫无压力。空间复杂度如果要保留每个字符的计数需要一个哈希表键的数量最多也就是字符串中出现的不同字符数量上限有限也不需要优化。真正需要留神的是后续中等题或难题会不会对时间卡得很紧。统计字符题本身不会成为时间瓶颈但如果你用了嵌套循环比如对每个字符再去统计全字符串中它出现的次数复杂度就变成O(n²)。字符串一长用例就会超时。这种错误在“删除最少出现字符”这题里尤其常见因为“统计每个字符次数”的直觉写法很容易写成双层循环。务必记住先一趟遍历统计频次哈希表后面所有查询都查表复用时耗为O(1)整体是O(n)这是唯一正确的复杂度模型。6. “统计字符”这类题暴露出的三段基本功6.1 基础不牢的人会卡在哪一步我帮别人review过不少这类题的答案发现三类最常见的卡点。第一类是输入读取。这个问题在C和Java选手里最突出基本都是因为平时刷题习惯用无空格的输入方式遇到带空格的字符串就读不全。第二类是字符判断逻辑的边界。比如中文字符被isLetter()判定为字母、制表符被isspace()当作空格这些都与题目预期不符。第三类是输出格式。题目要求用空格分隔有人用了换行题目要求输出四类计数有人只统计了三类或者把计数顺序搞反了。这三种错误都不涉及复杂算法但每一种都能让一道基础题拿不到满分。而这些能力恰恰就是“码代码”和“刷题”之间的差别刷题练的是算法的“巧”机考考的是解决问题的“稳”。6.2 围绕“统计字符”可以怎样安排练习路径如果你正在准备华为OD机考或类似岗位的笔试我不建议把“统计字符”当成一道题做完就结束。它可以作为一个训练单元向外扩展出一串题目先做基础的分类统计练输入读取和多分支判断。再做“删除最少出现字符”练哈希统计和二次遍历。然后做“输出出现次数最多的前K个字符”在统计的基础上引入排序。最后结合字符串反转、字符串去重组合出综合题练多知识点串联。每一次扩展都是在上一个题目的基础上加一层逻辑。这样练下来统计字符相关的一切考法基本都能覆盖。6.3 就题论题之外的体会说得更远一点统计字符这类题告诉我们一个朴素的道理编程基本功不是“知道”而是“做到”。你知道getline能读带空格的字符串和你在考场上条件反射地写出getline而不是cin s是完全两个层次的事情。这类送分题真正测试的就是你有没有把这些基础操作变成不假思索的肌肉记忆。我在实际带人和自己备考的经验里最深的体会是与其花大量时间刷难题不如先保证送分题100%拿满。把统计字符这种题的多语言实现、变体思路、边界用例都练到闭着眼睛能写对机考的心态和节奏都会有质的改善。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询