HJ21. 简单密码
题目描述
对密码进行转换:
- 小写字母按键盘九宫格映射为数字:a/b/c→2,d/e/f→3,g/h/i→4,j/k/l→5,m/n/o→6,p/q/r/s→7,t/u/v→8,w/x/y/z→9;
- 大写字母统一转为小写(不移动);
- 数字及其他字符保持不变。
输入格式
- 一行字符串(密码)。
输出格式
- 转换后的字符串。
示例
示例 1
输入:
YUANzhi1987
输出:
zvbo9441987
说明:
- 大写
Y U A N转小写后 ASCII 后移一位:Y→z、U→v、A→b、N→o - 小写
z h i按九宫格映射:z→9、h→4、i→4 - 数字
1987保持不变
解题思路
第一步:理解问题本质
字符分类处理:小写字母查表映射、大写字母转小写并后移、其他字符原样保留。
第二步:暴力解法(多重 if-else)
对每个字符用大量 if-else 判断属于哪个九宫格分组。
问题:代码冗长,容易写错某个字母的映射。
第三步:优化解法(映射表)
预先建立"小写字母 → 数字"的映射表,直接查表。
第四步:最优解法(映射表 + 字符分类)
- 小写字母:查表
LOWER_TO_DIGIT[ch]。 - 大写字母:转小写后,用取模运算使其 ASCII 后移一位(z 后移回到 a)。
- 其他:原样保留。
def convert(pwd: str) -> str:
res = []
for ch in pwd:
if ch.islower():
res.append(LOWER_TO_DIGIT[ch]) # 小写 -> 数字
elif ch.isupper():
# 大写 -> 转小写后,ASCII 后移一位(z 后移回到 a)
res.append(chr((ord(ch.lower()) - ord('a') + 1) % 26 + ord('a')))
else:
res.append(ch) # 数字/其他保持不变
return ''.join(res)
完整代码实现
算法可视化 · 逐帧回放这道题的代码24 帧 · 录制输入
import sys
# 小写字母 -> 数字的映射表
LOWER_TO_DIGIT = {
'a': '2', 'b': '2', 'c': '2',
'd': '3', 'e': '3', 'f': '3',
'g': '4', 'h': '4', 'i': '4',
'j': '5', 'k': '5', 'l': '5',
'm': '6', 'n': '6', 'o': '6',
'p': '7', 'q': '7', 'r': '7', 's': '7',
't': '8', 'u': '8', 'v': '8',
'w': '9', 'x': '9', 'y': '9', 'z': '9',
}
def convert(pwd: str) -> str:
"""转换单个密码"""
res = []
for ch in pwd:
if ch.islower():
res.append(LOWER_TO_DIGIT[ch]) # 小写 -> 数字
elif ch.isupper():
# 大写 -> 转小写后,ASCII 后移一位(z 后移回到 a)
res.append(chr((ord(ch.lower()) - ord('a') + 1) % 26 + ord('a')))
else:
res.append(ch) # 数字/其他保持不变
return ''.join(res)
def solve() -> None:
"""主求解函数"""
pwd = sys.stdin.readline().strip()
print(convert(pwd))
if __name__ == "__main__":
solve()
示例推演
以 YUANzhi1987 为例,逐字符转换:
| 字符 | 类型 | 转换 | 结果 |
|---|---|---|---|
| Y | 大写 | 转小写 y,后移一位 | z |
| U | 大写 | 转小写 u,后移一位 | v |
| A | 大写 | 转小写 a,后移一位 | b |
| N | 大写 | 转小写 n,后移一位 | o |
| z | 小写 | 查表 z→9 | 9 |
| h | 小写 | 查表 h→4 | 4 |
| i | 小写 | 查表 i→4 | 4 |
| 1 | 数字 | 不变 | 1 |
| 9 | 数字 | 不变 | 9 |
| 8 | 数字 | 不变 | 8 |
| 7 | 数字 | 不变 | 7 |
拼接结果:zvbo9441987。
复杂度分析
| 解法 | 时间复杂度 | 空间复杂度 | 说明 |
|---|---|---|---|
| 多重 if-else | O(L) | O(L) | 代码冗长易错 |
| 映射表 | O(L) | O(L) | 查表 O(1) |
L 为密码长度
易错点总结
1. 大写字母的处理
大写字母是先转小写再 ASCII 后移一位,不是直接映射到数字。注意 Z 后移要回到 a,用取模处理。
2. 九宫格映射
p/q/r/s 是 7(4 个字母),w/x/y/z 是 9(4 个字母),其余每组 3 个字母,容易记错。
3. 其他字符保留
数字和符号不参与任何转换,直接保留。
扩展思考
- 九宫格映射本质是一张静态表,用字典或数组存储均可,查表是 O(1)。
- 大写字母后移一类的循环移位,用
(x - base + delta) % 26 + base统一处理。