问题描述
小T设计了一种密码变换规则,将输入字符串转换为一串数字密码。变换规则如下:
-
小写字母转换规则:
小写字母根据电话按键上的分组映射为数字:a, b, c -> 2d, e, f -> 3g, h, i -> 4j, k, l -> 5m, n, o -> 6p, q, r, s -> 7t, u, v -> 8w, x, y, z -> 9
-
大写字母转换规则:
- 首先将大写字母转为小写字母。
- 转换为字母表中前一个字母,例如:
B转为a,A特殊处理转为z。 - 按上述小写字母的规则转换为数字。
-
非字母字符保持不变。
输入输出
- 输入:一个字符串
s,包含大小写字母和数字。 - 输出:按规则转换后的数字密码字符串。
样例分析
-
示例1:
输入:"LIming0701"
输出:"5464640701"
解析:'L'转为'k',映射为5'I'转为'h',映射为4- 其他小写字母按规则映射,数字保持不变。
-
示例2:
输入:"PassW0rd"
输出:"62778073"
解析:'P'转为'o',映射为6'W'转为'v',映射为8- 其他字母按规则映射。
二、解题思路
核心思路
- 遍历字符串,将大写字母转为小写字母的前一个字母。
- 构建一个映射表,将小写字母按电话键规则映射到数字。
- 根据映射表替换字符串中的字母,非字母字符保持不变。
三、代码实现
C++代码
#include <cctype>
#include <iostream>
#include <string>
#include <unordered_map>
using namespace std;
// 解决密码映射问题
string solution(const string &s) {
string res = s;
// 步骤1:将大写字母转为小写字母的前一个字母
for (auto &x : res) {
if (isupper(x)) {
if (x == 'A') // 特殊处理 A
x = 'Z';
else
x--; // 转换为前一个字母
x = tolower(x); // 转为小写
}
}
// 步骤2:构建小写字母到数字的映射表
unordered_map<char, char> hash;
char alp = 'a';
char code = '1';
// 按照题目规则生成映射
for (int i = 0; i < 26; i++) {
if (i % 3 == 0 && code < '7')
code++;
else if (i < 22 && i > 18 && code != '8')
code = '8';
else if (i > 21)
code = '9';
hash[alp] = code;
alp++;
}
// 步骤3:替换字母为对应的数字
for (auto &x : res) {
if (isalpha(x)) {
x = hash[x]; // 替换为数字
}
}
return res;
}
int main() {
// 测试样例
std::cout << solution("LIming0701") << std::endl; // 输出:5464640701
std::cout << solution("PassW0rd") << std::endl; // 输出:62778073
std::cout << solution("fbbMIjHoLAidgGr") << std::endl; // 输出:32255454444347
return 0;
}
四、代码解析
1. 处理大写字母
-
如果字符是大写字母:
- 特殊处理
A,变为Z; - 其他大写字母变为其前一个字母;
- 转换为小写字母。
代码:
- 特殊处理
if (isupper(x)) {
if (x == 'A')
x = 'Z';
else
x--;
x = tolower(x);
}
2. 构建字母映射表
构造小写字母到数字的映射,按题目要求,a~z 被分成不同的数字分组:
a, b, c -> 2,d, e, f -> 3,依此类推;- 使用哈希表存储映射关系。
代码:
unordered_map<char, char> hash;
char alp = 'a';
char code = '1';
for (int i = 0; i < 26; i++) {
if (i % 3 == 0 && code < '7')
code++;
else if (i < 22 && i > 18 && code != '8')
code = '8';
else if (i > 21)
code = '9';
hash[alp] = code;
alp++;
}
3. 替换字符
遍历字符串,将字母按映射表替换为数字,其他字符保持不变:
for (auto &x : res) {
if (isalpha(x)) {
x = hash[x];
}
}
五、时间复杂度分析
- 预处理映射表:
构建字母到数字的映射表是固定操作,时间复杂度为 O(26)O(26)。 - 遍历字符串:
遍历字符串并根据规则替换,每个字符操作时间复杂度为 O(1)O(1)。字符串长度为 nn,所以时间复杂度为 O(n)O(n)。
总时间复杂度:O(n)O(n) 。
六、总结
算法特点
- 代码清晰,逻辑分层明确。
- 使用哈希表快速实现字母到数字的映射,时间效率高。
适用场景
- 本算法可应用于密码生成、字符映射等问题,尤其适合简单的加密规则实现。
改进方向
- 可以进一步优化映射表的构建过程,使代码更简洁易读。
- 对其他字符的处理逻辑可扩展为多种映射规则,以增强通用性。
输出验证
通过样例测试,算法输出正确,符合题目要求。