To Lower Case
你会得到一个字符串 s。返回一个新字符串,其中每个大写英文字母(从 A 到 Z)都替换为对应的小写字母。其他所有字符,例如小写字母、数字或符号,都保持原样。
函数
- sstring
- 要转换的文本
- 返回值string
- 将所有大写字母都转换为小写后的 s
约束条件
1 ≤ s.length ≤ 104- 每个
s字符都是英文字母、数字,或以下符号之一:!#$%&()*+-./:;<=>?@[]^_`{|}~。
示例
- 输入
- s = "Hello-World!"
- 输出
- "hello-world!"
- 解释
- 大写字母
H和W会变成h和w。-和!不是字母,所以它们保持原样。
- 输入
- s = "coddy_2026"
- 输出
- "coddy_2026"
- 解释
- 没有需要转换的大写字母。小写字母、
_和数字都会保持不变。
- 输入
- s = "SQL"
- 输出
- "sql"
- 解释
- 这三个字符都是大写字母,所以它们都会转换为对应的小写字母。
进阶
你能用相同的循环写出 toUpperCase,并解释为什么 A 和 a 的字符编码只有一位不同吗?
提示
逐个打开提示,每个都会多透露一点。
计算机会将每个字符存储为一个数字。
A和a对应的数字有什么关系?A到Z的编码是 65 到 90,a到z的编码是 97 到 122。每个大写字母的编码都比对应的小写字母低 32。逐个处理字符。当编码在 65 到 90 之间时,加上 32;否则保留该字符。收集处理结果,并将它们合并成答案。
题解
每种语言都自带一个小写转换函数,在生产代码中你应该调用它。面试官会问这个问题,看看你是否知道它的工作原理:在 ASCII 中,每个大写字母的编码都恰好比对应的小写字母低 32,所以你要给 'A' 到 'Z' 之间的每个编码加上 32。
调用内置的小写转换函数
思路
Python 的 lower()、JavaScript 的 toLowerCase()、Ruby 的 downcase 及其同类函数已经能完成这项工作;C 和 C++ 提供了用于处理单个字符的 tolower,因此你需要在循环中调用它。每个字符只检查一次,时间复杂度为 O(n),新字符串需要 O(n) 的空间。
其中一些函数会遵循计算机的语言设置。在土耳其语中,I 的小写形式是没有点的 ı,因此 Java 和 C# 版本会使用 Locale.ROOT 和 ToLowerInvariant 指定固定规则。在面试中,这种答案往往不被接受,因为它掩盖了题目真正考查的思路。
算法
- 对
s调用你所用语言的小写转换函数,或者在 C 和 C++ 中对每个字符调用tolower。 - 如果该函数提供固定且与语言无关的规则,请使用该规则。
- 返回结果。
def toLowerCase(s):
return s.lower()将大写字母的字符编码偏移
思路
每个字符都以数字形式存储。在 ASCII 中,A 到 Z 的编码是 65 到 90,a 到 z 的编码是 97 到 122。两组编码都按字母顺序排列,而且起始值相差 32,所以任意大写字母对应的小写字母编码都是它的编码加 32:H 的编码是 72,h 的编码是 104。只有编码在 65 到 90 之间的字符会改变;像 _ 这样的符号位于 Z 和 a 之间,必须原样复制。
每个字符只检查一次,时间复杂度为 O(n);答案是一个长度相同的新字符串,空间复杂度为 O(n)。用 'a' - 'A' 代替 32,可以看出这个数字是怎么来的。
算法
- 将
s复制到由字符或代码组成的数组中。 - 对于每个位置,读取字符代码。
- 如果代码介于
'A'(65)和'Z'(90)之间,就加上 32。 - 将数组转换回字符串并返回。
def toLowerCase(s):
# Every capital letter sits 32 codes below its small letter: 'A' is 65, 'a' is 97.
shift = ord("a") - ord("A")
chars = []
for ch in s:
if "A" <= ch <= "Z":
ch = chr(ord(ch) + shift)
chars.append(ch)
return "".join(chars)
易错点和边界情况
- 给每个非小写字符加上 32。数字和符号也会改变:
1会变成Q。 - 只检查范围的一端。
code < 'a'也会匹配[、_和@,而code >= 'A'也会匹配所有小写字母。 - 在范围端点使用
<而不是<=,会导致A或Z保持大写。 - 对不可变字符串使用
result = result + ch来构建答案。每一步都会复制目前为止的所有内容,因此当n = 10^4时,时间复杂度为平方级。 - 在 C 中,直接写入输入内容,或忘记添加终止符
'\0'。为副本分配n + 1个字节。
常见问题3
为什么大写字母和小写字母之间的差值是 32?
ASCII 将大写字母放在编码 65 到 90 的位置,将小写字母放在编码 97 到 122 的位置,中间有 6 个符号。两组字母的顺序相同,因此每对字母的编码相差 97 - 65 = 32。32 对应一个二进制位,因此设置该位就能将大写字母转换为对应的小写字母。
你能用位运算改变大小写吗?
是的。对于大写字母,code | 32 会设置区分大小写的位,并得到对应的小写字母;code & ~32 则会再次清除该位。你仍然需要先检查范围,因为同样的位运算技巧也会改变数字和符号。
将字符串转换为小写的时间复杂度是多少?
对于长度为 n 的字符串,时间复杂度是 O(n),因为每个字符都会检查一次。新字符串需要 O(n) 的空间。如果你可以原地修改字符数组,额外空间就会降到 O(1)。
相似题目
运用相同思路的题目。做两三道,才能真正掌握一种模式。
def toLowerCase(s):
# 在这里编写代码测试 #1
测试 #2
测试 #3
参数
s = "Hello-World!"
预期输出
"hello-world!"