- 教程
- 文档
- 知识库
【免费下载链接】AlgoNote
⛽️「算法通关手册」:从零开始的「算法与数据结构」学习教程,200 道「算法面试热门题目」,1000+ 道「LeetCode 题目解析」,持续更新中!
导读
本篇题解围绕 LeetCode 0520「检测大写字母」(Detect Capital)展开,是「算法通关手册」AlgoNote 中字符串基础分类下的经典入门题。题目要求判断一个英文单词的大写用法是否符合英语书写规范(全大写、全小写、仅首字母大写三种合法情况)。读完本文,你将掌握基于字符串字符遍历的计数判型思路,理解 Python 中str.isupper()等字符分类方法的底层行为,并能够将这一「模式判定」思想迁移到其他字符串校验类问题中。本仓库中对应题解文档位于 docs/solutions/0500-0599/detect-capital.md。
1. 题目分析
1.1 题目链接与基本信息
- 题号:0520,标签为「字符串」,难度为「简单」。
- 题目链接:0520. 检测大写字母(力扣原题)。
该题在本仓库的题解索引中被归类为字符串基础题目,可参见 docs/solutions/0500-0599/index.md 与 docs/00_preface/00_05_solutions_list.md(后者按题号收录了全量 LeetCode 题解清单,其中 0520 一栏标注为:字符串 / 简单)。
1.2 题目大意
我们定义,在以下三种情况下,单词的大写用法是正确的:
- 全部字母都是大写,比如
"USA"; - 所有字母都不是大写(即全小写),比如
"leetcode"; - 只有首字母大写,比如
"Google"。
给定一个字符串word,如果大写用法正确则返回true,否则返回false。
说明(数据范围):
- $1 \le word.length \le 10^{3}$;
word由小写和大写英文字母组成。
示例:
# 示例 1 输入:word = "USA" 输出:true # 示例 2 输入:word = "FlaG" 输出:false示例 2 的"FlaG"之所以不正确,是因为它既不是全大写(末尾G前还有小写a)、不是全小写,也不是「仅首字母大写」(首字母F大写,但第 3 个字母G也是大写),因此返回false。
2. 解题思路:分类判断(计数判型)
2.1 核心思想
题目给出的三种合法情况本质上是对字符串中大写字母分布的约束。因此最直观的做法是:
- 遍历字符串,统计其中大写字母的数量
upper_count; - 同时获取字符串总长度
n; - 根据
upper_count与n的关系以及首字母大小写,判定属于哪一种合法模式。
判定规则可以归纳为如下表格:
| 条件 | 判定结果 | 对应合法模式 |
|---|---|---|
upper_count == 0 | True | 所有字母都不是大写(全小写) |
upper_count == n | True | 全部字母都是大写 |
upper_count == 1且word[0]是大写 | True | 只有首字母大写 |
| 其他情况 | False | 不合法 |
注意第三条的完整语义:当upper_count == 1时,唯一的那个大写字母必须是首字母,所以还要验证word[0].isupper()。如果唯一的那个大写字母出现在非首字母位置(例如"FlaG"中的G),则upper_count == 1成立但word[0].isupper()为False,应返回False。
2.2 代码实现
原题解给出的 Python 实现如下:
class Solution: def detectCapitalUse(self, word: str) -> bool: n = len(word) upper_count = sum(1 for c in word if c.isupper()) # 全部小写 if upper_count == 0: return True # 全部大写 if upper_count == n: return True # 只有首字母大写 if upper_count == 1 and word[0].isupper(): return True return False2.3 代码要点解读
sum(1 for c in word if c.isupper())使用生成器表达式统计大写字母数量,等价于手写循环累加,代码更简洁;str.isupper()是 Python 字符串的内置方法,对单个字符调用时判断该字符是否为大写英文字母;对非字母字符(如数字、符号)isupper()返回False。本题输入约束保证word只含英文字母,因此可以放心使用;- 三个
if分支互斥且覆盖了全部合法情况,其余情况统一落入最后的return False,逻辑完整无遗漏。
2.4 复杂度分析
- 时间复杂度:$O(n)$,其中 $n$ 是字符串长度。只需一次遍历统计大写字母数量,后续判断均为 $O(1)$ 操作;
- 空间复杂度:$O(1)$,仅使用
n、upper_count等常数额外变量,不随输入规模增长。
3. 从源码看字符串基础:字符分类与遍历模式
3.1 字符串遍历与字符编码背景
本题属于「字符串基础」类问题,而 AlgoNote 在 docs/04_string/04_01_string_basic.md 中系统介绍了字符串的核心概念:字符串是由零个或多个字符组成的有限序列,支持按下标随机访问,其大小比较本质上是对字符编码(如 ASCII 中大写字母A编码 65、小写字母a编码 97)的逐字符比较。
理解这一点有助于深入本题的判定逻辑:大写字母与小写字母在编码表中是连续分段排列的,因此「判断某个字符是否为大写」天然适合用内置分类方法完成,而不需要手写 ASCII 码区间比较。
3.2 仓库中的字符遍历与比较实现
本仓库codes/python/04_string/目录下的源码展示了大量字符串遍历与比较的实践,可作为本题的横向参照:
- codes/python/04_string/string_Strcmp.py 实现了
strcmp(str1, str2),通过ord(str1[index])逐字符比较编码值,并附带多组测试用例(如"123"与"123"返回 0、"123"与"124"返回 -1),体现了「逐字符扫描 + 内置函数」这一与本题一致的基本编程范式; - codes/python/04_string/string_trie.py 中的字典树(Trie)实现,其
insert/search方法同样采用for ch in word逐字符遍历的方式处理字符串,可见字符串类算法题普遍围绕「逐字符访问」这一核心操作展开。
本题代码中sum(1 for c in word if c.isupper())与上述源码一样,本质都是对字符串做一次线性扫描,只是判定条件换成了大小写分类。
4. 变式与拓展:其他等价实现方式
除了「计数判型」,同一问题还可以从以下角度实现,均保持 $O(n)$ 时间、$O(1)$ 空间:
4.1 直接模式判断(不显式计数)
利用首字母与剩余部分的大小写关系直接推导:
class Solution: def detectCapitalUse(self, word: str) -> bool: # 全大写:word == word.upper() # 全小写:word == word.lower() # 首字母大写:word[0].isupper() and word[1:] == word[1:].lower() return word == word.upper() or word == word.lower() \ or (word[0].isupper() and word[1:].lower() == word[1:])注意:
word[1:].lower() == word[1:]等价于「除首字母外全部小写」。空串切片word[1:]在len(word) == 1时为空串,此时该条件恒真,恰好覆盖单个大写字母(如"A")这类合法输入。
4.2 分段判定(首字符 + 尾部)
先确定首字母的大小写,再检查剩余部分是否满足对应规则:
class Solution: def detectCapitalUse(self, word: str) -> bool: first = word[0].isupper() if first: # 首字母大写:剩余部分要么全大写、要么全小写 return word[1:].isupper() or word[1:].islower() # 首字母小写:剩余部分必须全部小写 return word[1:].islower()注意""(空串)的isupper()/islower()均返回False,因此长度为 1 的单词"a"走第二条分支时word[1:].islower()为False,会错误返回False。要处理长度为 1 的输入,需要显式加上len(word) == 1的特判,或改用第 4.1 节不依赖空串特性的写法。相比之下,原题解的「计数判型」对任意合法长度输入都不需要特判,这是它实现更稳健的原因。
4.3 各实现方式对比
| 实现方式 | 核心判定依据 | 边界情况处理 | 可读性 |
|---|---|---|---|
| 计数判型(原题解) | 大写数量upper_count与长度n的关系 | 天然覆盖单字符等边界 | 高 |
| 整体模式比较 | 与upper()/lower()结果比较 | 单字符自动正确 | 高 |
| 分段判定 | 首字符 + 剩余部分分类 | 需显式特判单字符 | 中 |
从源码结构看,三种写法的时间、空间复杂度完全一致,实际竞赛与面试中任选其一均可;原题解选择计数判型,主要因其条件与题目定义的三条规则一一对应、不易遗漏边界。
5. 举一反三:同类字符串校验问题
检测大写字母是典型的「字符串模式校验」题,其「统计 + 判型」的思路可以推广到本仓库题解集中多个字符串基础题目,例如:
- 125. 验证回文串:同样需要逐字符判断是否为字母数字,再比较字符,属于字符分类 + 遍历的经典组合;
- 344. 反转字符串:基于下标随机访问的线性操作;
- 557. 反转字符串中的单词 III:在遍历字符串的同时按字符(空格)切分处理子串。
这些题目在 docs/04_string/04_01_string_basic.md 末尾的「练习题目」一节中亦有收录,可与本篇对照练习。
6. 小结
0520「检测大写字母」虽为简单题,却完整覆盖了字符串题目的三个基本功:
- 逐字符遍历:通过
isupper()完成字符分类统计,是处理字符串最常见的基础操作; - 模式归纳:将题目文字描述的三条规则映射为可判定的逻辑条件,是解题的关键步骤;
- 边界意识:理解单字符、空切片等边界输入在不同实现下的行为差异,避免写出「对简单用例正确、对边界出错」的代码。
原题解采用「计数判型」在 $O(n)$ 时间内完成判定,空间开销仅 $O(1)$,实现简洁且对边界输入稳健,可作为此类字符串校验题的标准解法模板,也可以继续在 docs/04_string/index.md 中查阅更多字符串算法与题解。
- 教程
- 文档
- 知识库
【免费下载链接】AlgoNote
⛽️「算法通关手册」:从零开始的「算法与数据结构」学习教程,200 道「算法面试热门题目」,1000+ 道「LeetCode 题目解析」,持续更新中!
相关推荐
javascript.info 实战任务解析:用 ucFirst 实现 JavaScript 字符串首字母大写
javascript.info 实战任务解析:用 ucFirst 实现 JavaScript 字符串首字母大写 导读 本文围绕 Modern JavaScrip
文档/教程前端type-challenges 题解:用模板字面量类型实现 `Capitalize<T>`,将字符串首字母大写
type challenges 题解:用模板字面量类型实现 Capitalize<T ,将字符串首字母大写 导读 本篇文章围绕 type challenges
示例工程如何使用polished实现字符串首字母大写:capitalizeString函数完全指南
如何使用polished实现字符串首字母大写:capitalizeString函数完全指南 polished是一个轻量级的JavaScript样式工具库,提供了
前端UI组件
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考