转换成小写字母 图解题解
这道题到底在问什么
- 输入
- s = "Hello"
- 输出
- "hello" (只有 H 是大写,转成 h)
- 输入
- s = "LOVELY"
- 输出
- "lovely" (六个字母全大写,全部转小写)
- 输入
- s = "here"
- 输出
- "here" (本就全小写,原样返回)
先想最直接的笨办法
先把整条串摆出来。大写字母 A、C、E、G、I 夹在小写 b、d、f、h、j 中间。我们从第 0 个开始,一个一个过。(动画第 4 步)
最优解:一步一步想明白
- 3记住这把尺子:大写小写在 ASCII 表里成对排列,每对正好差 32。下面每一帧都在套「在范围就 +32,不在就放过」。
- 4先把整条串摆出来。大写字母 A、C、E、G、I 夹在小写 b、d、f、h、j 中间。我们从第 0 个开始,一个一个过。
- 5轮到第 0 个字符 「A」,它的 ASCII 码是 65。先问:这个码落在 65 到 90 之间吗,也就是它是不是大写字母?
- 6「A」 是大写,该转。给它的码 65 加上 32(用位运算 | 32 一步到位)得到 97,也就是小写 「a」。第 0 格变绿,表示这一格已经转好了。
- 7轮到第 1 个字符 「b」,它的 ASCII 码是 98。先问:这个码落在 65 到 90 之间吗,也就是它是不是大写字母?
- 8「b」 的码 98 不在 65 到 90 这一段,它本来就是小写,什么都不用做,原样留下。第 1 格标蓝,表示看过、未改。
- 9轮到第 2 个字符 「C」,它的 ASCII 码是 67。先问:这个码落在 65 到 90 之间吗,也就是它是不是大写字母?
- 10「C」 是大写,该转。给它的码 67 加上 32(用位运算 | 32 一步到位)得到 99,也就是小写 「c」。第 2 格变绿,表示这一格已经转好了。
- 11轮到第 3 个字符 「d」,它的 ASCII 码是 100。先问:这个码落在 65 到 90 之间吗,也就是它是不是大写字母?
- 12「d」 的码 100 不在 65 到 90 这一段,它本来就是小写,什么都不用做,原样留下。第 3 格标蓝,表示看过、未改。
- 13轮到第 4 个字符 「E」,它的 ASCII 码是 69。先问:这个码落在 65 到 90 之间吗,也就是它是不是大写字母?
- 14「E」 是大写,该转。给它的码 69 加上 32(用位运算 | 32 一步到位)得到 101,也就是小写 「e」。第 4 格变绿,表示这一格已经转好了。
- 15轮到第 5 个字符 「f」,它的 ASCII 码是 102。先问:这个码落在 65 到 90 之间吗,也就是它是不是大写字母?
- 16「f」 的码 102 不在 65 到 90 这一段,它本来就是小写,什么都不用做,原样留下。第 5 格标蓝,表示看过、未改。
- 17轮到第 6 个字符 「G」,它的 ASCII 码是 71。先问:这个码落在 65 到 90 之间吗,也就是它是不是大写字母?
- 18「G」 是大写,该转。给它的码 71 加上 32(用位运算 | 32 一步到位)得到 103,也就是小写 「g」。第 6 格变绿,表示这一格已经转好了。
- 19轮到第 7 个字符 「h」,它的 ASCII 码是 104。先问:这个码落在 65 到 90 之间吗,也就是它是不是大写字母?
- 20「h」 的码 104 不在 65 到 90 这一段,它本来就是小写,什么都不用做,原样留下。第 7 格标蓝,表示看过、未改。
- 21轮到第 8 个字符 「I」,它的 ASCII 码是 73。先问:这个码落在 65 到 90 之间吗,也就是它是不是大写字母?
- 22「I」 是大写,该转。给它的码 73 加上 32(用位运算 | 32 一步到位)得到 105,也就是小写 「i」。第 8 格变绿,表示这一格已经转好了。
- 23轮到第 9 个字符 「j」,它的 ASCII 码是 106。先问:这个码落在 65 到 90 之间吗,也就是它是不是大写字母?
- 24「j」 的码 106 不在 65 到 90 这一段,它本来就是小写,什么都不用做,原样留下。第 9 格标蓝,表示看过、未改。
- 25十个字符全部过了一遍。绿色的 5 个是从大写转来的,蓝色的 5 个本就是小写、原样保留,拼起来就是答案 abcdefghij。整个过程一遍扫描、没有回头。
⚠️ 容易写错的地方
✗ 错:用 +32 时忘了先判是不是大写
✓ 对:只对 A 到 Z 加 32,其它一律不动
给小写或数字、符号也加 32 会把它们改成别的字符,结果全乱
✗ 错:把判定范围写成 65 到 91 或 64 到 90
✓ 对:严格 65 ≤ c ≤ 90
边界差一位会漏掉 Z 或误把 [ 当字母,字符表上要数准
✗ 错:以为 | 32 和 + 32 不一样
✓ 对:对大写字母两者结果相同
大写字母的 ASCII 第 5 位(值 32)本来是 0,加 32 和按位或 32 等价
完整代码(Python / C++ / Java)
Python
from __future__ import annotations
from typing import *
from collections import *
from functools import *
from itertools import *
from math import *
from heapq import *
from bisect import *
class Solution:
def toLowerCase(self, s: str) -> str:
return "".join([chr(ord(c) | 32) if c.isupper() else c for c in s])C++
#include <algorithm>
#include <array>
#include <cctype>
#include <climits>
#include <cmath>
#include <deque>
#include <functional>
#include <iostream>
#include <limits>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>
using namespace std;
class Solution {
public:
string toLowerCase(string s) {
for (char& c : s) {
if (c >= 'A' && c <= 'Z') {
c |= 32;
}
}
return s;
}
};Java
import java.util.*;
class Solution {
public String toLowerCase(String s) {
char[] cs = s.toCharArray();
for (int i = 0; i < cs.length; ++i) {
if (cs[i] >= 'A' && cs[i] <= 'Z') {
cs[i] |= 32;
}
}
return String.valueOf(cs);
}
}复杂度
时间
O(n)
每个字符只看一次,n 是串长
空间
O(n)
需要一个等长的结果串(字符串通常不可原地改);C++ 传值副本上原地改也是 O(n)
看不够?换成动画再走一遍
上面的推演每一步都对应一帧动画。点开交互动画版,能一步步看着 转换成小写字母 的数据怎么变、指针怎么走,还能切 Python / Java / C++ 跟着练。
面试官可能追问
为什么大写转小写可以用位运算 | 32?+
看 ASCII 二进制:大写 A 到 Z 是 0x41 到 0x5A,小写 a 到 z 是 0x61 到 0x7A,同一个字母的大小写只差第 5 位(值 32)那一个比特,大写该位是 0、小写是 1。所以把大写的第 5 位置 1(即 | 32)就变小写;反过来把该位清 0(& ~32)就变大写。这比加减更能体现本质。
如果不让用库函数 tolower,怎么写最稳?+
就用本题这套:判 c 是否在 65 到 90 之间,是就 c | 32 或 c + 32,否就保留。注意一定要先判范围,不能无脑加 32,否则会破坏非大写字符。这也是 tolower 内部大致在做的事。
想听吴师兄把这道题讲给你听?
文字版和动画都随便看。开通图解算法年卡,可以听吴师兄声线把 转换成小写字母 一步步讲透(全站 0 节语音精讲,持续扩充), 卡住的地方还有 AI 私教小欧就着动画帮你拆到懂。
本平台为独立第三方培训机构,与华为技术有限公司无任何关联;课程的服务内容与权益以购买协议为准,学习效果因个人情况而异。「华为 OD」「华为可信」等仅为对岗位与考试方向的客观描述,相关商标归各自权利人所有。