机考在线训练题解析
在华为机试题库中,很多题目都是字符串处理相关的基础算法题。本文将详细解析涵盖字符串加解密、字符串合并处理、单词倒排三个问题。每个题目都附带思路讲解与完整代码,适合新手学习。
题目29:字符串加解密
题目描述
编写程序实现对字符串的加解密功能:
-
加密规则
-
英文字母用其后一个字母替换,且需要区分大小写
- A → B,Z → a
- a → B,z → A
-
数字加1,9变为0
-
其他字符保持不变
-
-
解密规则
-
与加密相反:
- B → a,A → z
- 0 → 9
- 其他字符保持不变
-
要求实现两个函数:
encrypt(string s)
decrypt(string s)
解题思路
-
遍历输入字符串,逐个字符处理。
-
对于字母:
- 小写字母加密后变成大写字母(往后移一位)
- 大写字母加密后变成小写字母(往后移一位)
- 遇到边界(如 z 或 Z)时要循环。
-
对于数字:
0 → 1
,9 → 0
-
其他字符保持不变。
-
解密过程与加密完全对称。
代码实现(详细注释)
#include <iostream>
#include <string>
using namespace std;
// 加密函数
string encrypt(const string& str) {
string res;
for (char c : str) {
if (c >= 'a' && c <= 'z') {
// 小写字母 → 下一位大写字母
res += (c == 'z' ? 'A' : char(c + 1 - 32));
} else if (c >= 'A' && c <= 'Z') {
// 大写字母 → 下一位小写字母
res += (c == 'Z' ? 'a' : char(c + 1 + 32));
} else if (c >= '0' && c <= '9') {
// 数字 → 加1,9变成0
res += (c == '9' ? '0' : char(c + 1));
} else {
// 其他字符不变
res += c;
}
}
return res;
}
// 解密函数
string decrypt(const string& str) {
string res;
for (char c : str) {
if (c >= 'a' && c <= 'z') {
// 小写字母 → 前一位大写字母
res += (c == 'a' ? 'Z' : char(c - 1 - 32));
} else if (c >= 'A' && c <= 'Z') {
// 大写字母 → 前一位小写字母
res += (c == 'A' ? 'z' : char(c - 1 + 32));
} else if (c >= '0' && c <= '9') {
// 数字 → 减1,0变成9
res += (c == '0' ? '9' : char(c - 1));
} else {
res += c;
}
}
return res;
}
int main() {
string s;
while (getline(cin, s)) {
// 输出加密结果
cout << encrypt(s) << endl;
// 输出解密结果
cout << decrypt(s) << endl;
}
return 0;
}
题目30:字符串合并处理
题目描述
输入两个字符串,进行如下操作:
- 将两个字符串合并。
- 将合并后的字符串分成奇数位和偶数位两个部分,分别排序。
- 将排序后的奇数位和偶数位重新合并。
- 对合并结果中的字符,如果它是
0-9
、A-F
或a-f
,则将其转为16进制数并进行 二进制位倒序,再转换回字符。
解题思路
- 合并两个字符串 →
merged
。 - 遍历
merged
,分成odd
(奇数位)和even
(偶数位)。 - 对
odd
和even
分别排序。 - 按原顺序合并回来。
- 遍历新字符串,对
0-9
、A-F
、a-f
的字符进行 16进制 → 二进制 → 倒序 → 新字符 的转换。
示例
输入:
dec fab
合并:decfab
奇数位:dca
→ 排序:acd
偶数位:efb
→ 排序:bef
合并:abcdef
16进制倒序后 → 5D37BF
代码实现(详细注释)
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <cctype>
using namespace std;
// 将16进制字符转换成倒序后的字符
char reverseHex(char c) {
int val;
if (c >= '0' && c <= '9') val = c - '0';
else if (c >= 'A' && c <= 'F') val = c - 'A' + 10;
else if (c >= 'a' && c <= 'f') val = c - 'a' + 10;
else return c; // 非16进制字符直接返回
// 将val转换成4位二进制并倒序
int rev = 0;
for (int i = 0; i < 4; i++) {
rev = (rev << 1) | (val & 1);
val >>= 1;
}
// 转换回16进制字符(大写)
if (rev < 10) return rev + '0';
else return rev - 10 + 'A';
}
int main() {
string s1, s2;
while (cin >> s1 >> s2) {
string merged = s1 + s2;
// 分离奇数位和偶数位
string odd, even;
for (int i = 0; i < merged.size(); i++) {
if (i % 2 == 0) even += merged[i]; // 下标从0开始
else odd += merged[i];
}
// 排序
sort(odd.begin(), odd.end());
sort(even.begin(), even.end());
// 合并回去
string sortedStr;
int oi = 0, ei = 0;
for (int i = 0; i < merged.size(); i++) {
if (i % 2 == 0) sortedStr += even[ei++];
else sortedStr += odd[oi++];
}
// 进行16进制字符倒序处理
for (char &c : sortedStr) {
c = reverseHex(c);
}
cout << sortedStr << endl;
}
return 0;
}
题目31:单词倒排
题目描述
输入一句话,将单词倒序输出。
要求:
- 单词由 26个字母 组成。
- 非字母字符(如空格、标点)都视为分隔符。
- 输出时,单词之间只保留一个空格。
解题思路
- 遍历字符串,将非字母的地方替换成空格。
- 按空格切分单词,存入
vector
。 - 倒序输出
vector
中的单词。
示例
输入:
I am a student.
输出:
student a am I
代码实现(详细注释)
#include <iostream>
#include <string>
#include <vector>
#include <sstream>
using namespace std;
int main() {
string line;
// 读取整行输入
getline(cin, line);
stringstream ss(line);
string temp;
vector<string> words; // 存储单词
while (getline(ss,temp,' ')) {
words.push_back(temp);
// 遍历字符串,提取单词
}
// 倒序输出
for (int i = (int)(words.size()) - 1; i >= 0; i--) {
cout << words[i];
if (i > 0) cout << " "; // 单词之间一个空格
}
cout << endl;
return 0;
}
总结
- 29题:考察了字符的加解密(字母/数字循环处理)。
- 30题:考察字符串合并、奇偶分离排序以及16进制位倒序。
- 31题:考察单词提取与倒序输出,强调分隔符处理。
这三道题都非常经典,适合练习 字符串处理能力。