华为机试真题练习汇总(11~20)
华为机试真题练习汇总(11~20)
题目来源:华为机试 - 牛客
标记 * 号的代表有难度的题目。
HJ11 数字颠倒
描述
输入一个整数,将这个整数以字符串的形式逆序输出
程序不考虑负数的情况,若数字含有0,则逆序形式也含有0,如输入为100,则输出为001
输入描述:
输入一个int整数
输出描述:
将这个整数以字符串的形式逆序输出
代码:
#include <iostream>
using namespace std;
int main() {
int input;
cin >> input;
if (input == 0) {
cout << "0" << endl;
return 0;
}
string ans;
while (input) {
ans.push_back(input % 10 + '0');
input /= 10;
}
cout << ans << endl;
return 0;
}
// 64 位输出请用 printf("%lld")
HJ12 字符串反转
描述
接受一个只包含小写字母的字符串,然后输出该字符串反转后的字符串。(字符串长度不超过1000)
输入描述:
输入一行,为一个只包含小写字母的字符串。
输出描述:
输出该字符串反转后的字符串。
代码:
#include <algorithm>
#include <iostream>
using namespace std;
int main() {
string s;
cin >> s;
reverse(s.begin(), s.end());
cout << s << endl;
return 0;
}
// 64 位输出请用 printf("%lld")
HJ13 句子逆序
代码:
#include <vector>
#include <iostream>
#include <sstream>
using namespace std;
int main()
{
string s;
getline(cin, s);
stringstream ss(s);
string word;
vector<string> words;
while (ss >> word)
words.push_back(word);
for (int i = words.size() - 1; i >= 0; i--)
{
if (i)
cout << words[i] << ' ';
else
cout << words[i] << endl;
}
return 0;
}
// 64 位输出请用 printf("%lld")
HJ14 字符串排序
描述
给定 n 个字符串,请对 n 个字符串按照字典序排列。
输入描述:
输入第一行为一个正整数n(1≤n≤1000),下面n行为n个字符串(字符串长度≤100),字符串中只含有大小写字母。
输出描述:
数据输出n行,输出结果为按照字典序排列的字符串。
代码:
#include <algorithm>
#include <iostream>
#include <ostream>
#include <vector>
using namespace std;
int main() {
int n;
cin >> n;
vector<string> words;
for (int i = 0; i < n; i++)
{
string s;
cin >> s;
words.push_back(s);
}
sort(words.begin(), words.end());
for (string word : words)
cout << word << endl;
return 0;
}
// 64 位输出请用 printf("%lld")
HJ15 求int型正整数在内存中存储时1的个数
描述
输入一个 int 型的正整数,计算出该 int 型数据在内存中存储时 1 的个数。
数据范围:保证在 32 位整型数字范围内
输入描述:
输入一个整数(int类型)
输出描述:
这个数转换成2进制后,输出1的个数
代码 1:
#include <iostream>
using namespace std;
int main() {
int n;
cin >> n;
int count = 0;
while (n) {
count += n % 2;
n >>= 1;
}
cout << count << endl;
return 0;
}
// 64 位输出请用 printf("%lld")
代码 2:
n = n & (n-1),可以消去 n 二进制位中最右边的 1 个 1。
#include <iostream>
using namespace std;
int main() {
int n;
cin >> n;
int count = 0;
while (n) {
n &= (n - 1);
count++;
}
cout << count << endl;
return 0;
}
// 64 位输出请用 printf("%lld")
* HJ16 购物单
代码:
#include <iostream>
#include <vector>
using namespace std;
int main() {
int N, m;
cin >> N >> m;
// 价格
vector<vector<int>> prices(61, vector<int>(3, 0));
// 满意度是指所购买的每件物品的价格与重要度的乘积
vector<vector<int> > favors(61, vector<int>(3, 0));
for (int i = 1; i <= m; i++) {
int v, p, q;
// v 是价格,p 是重要度,q 是主件编号
cin >> v >> p >> q;
int favor = v * p;
if (q == 0) {
prices[i][0] = v;
favors[i][0] = favor;
} else {
if (prices[q][1] == 0) {
prices[q][1] = v;
favors[q][1] = favor;
} else {
prices[q][2] = v;
favors[q][2] = favor;
}
}
}
// 状态数组
vector<vector<int> > dp(m + 1, vector<int>(N + 1, 0));
// 状态转移
for (int i = 1; i <= m; i++)
for (int j = 1; j <= N; j++) {
int p0 = prices[i][0], f0 = favors[i][0];
int p1 = prices[i][1], f1 = favors[i][1];
int p2 = prices[i][2], f2 = favors[i][2];
// 状态转移方程
dp[i][j] = dp[i - 1][j];
if (j >= p0)
dp[i][j] = max(dp[i - 1][j - p0] + f0, dp[i - 1][j]);
if (j >= (p0 + p1))
dp[i][j] = max(dp[i - 1][j - (p0 + p1)] + f0 + f1, dp[i][j]);
if (j >= (p0 + p2))
dp[i][j] = max(dp[i - 1][j - (p0 + p2)] + f0 + f2, dp[i][j]);
if (j >= (p0 + p1 + p2))
dp[i][j] = max(dp[i - 1][j - (p0 + p1 + p2)] + f0 + f1 + f2, dp[i][j]);
}
cout<<dp[m][N]<<endl;
return 0;
}
// 64 位输出请用 printf("%lld")
HJ17 坐标移动
代码:
#include <cctype>
#include <iostream>
#include <sstream>
using namespace std;
int main()
{
string str;
cin >> str;
stringstream ss(str);
const char split = ';';
string move;
int x = 0, y = 0;
while (getline(ss, move, split)) {
char dir = move[0];
bool judge = true;
int distance = 0;
for (int i = 1; i < move.length(); i++) {
if (isdigit(move[i])) {
distance = 10 * distance + move[i] - '0';
} else {
judge = false;
break;
}
}
if (judge) {
switch (dir) {
case 'A':
x -= distance;
break;
case 'D':
x += distance;
break;
case 'W':
y += distance;
break;
case 'S':
y -= distance;
break;
default:
break;
}
}
}
cout << x << "," << y << endl;
return 0;
}
// 64 位输出请用 printf("%lld")
* HJ18 识别有效的IP地址和掩码并进行分类统计
代码:
#include <iostream>
#include <sstream>
#include <vector>
using namespace std;
bool judge_ip(const string ip) {
int j = 0;
stringstream ss(ip);
string seg;
while (getline(ss, seg, '.'))
if (++j > 4 || seg.empty() || stoi(seg) > 255)
return false;
return j == 4;
}
bool is_mask(const string ip) {
stringstream ss(ip);
string seg;
unsigned int b = 0;
while (getline(ss, seg, '.'))
b = (b << 8) + stoi(seg);
if (b == 0 || ~b == 0) {
// 二进制下全是1或者全是0均为非法子网掩码
return false;
}
b = ~b + 1;
if ((b & (b - 1)) == 0)
return true;
return false;
}
bool is_private(const string ip) {
istringstream iss(ip);
string seg;
vector<int> v;
while (getline(iss, seg, '.'))
v.push_back(stoi(seg));
if (v[0] == 10)
return true;
if (v[0] == 172 && (v[1] >= 16 && v[1] <= 31))
return true;
if (v[0] == 192 && v[1] == 168)
return true;
return false;
}
int main()
{
string line;
int a = 0, b = 0, c = 0, d = 0, e = 0, err = 0, p = 0;
while (cin >> line) {
int split_index = line.find('~');
string ip = line.substr(0, split_index);
string mask = line.substr(split_index + 1);
int idx = ip.find_first_of('.');
int first = stoi(ip.substr(0, idx));
// 类似于【0.*.*.*】和【127.*.*.*】的IP地址不属于上述输入的任意一类,
// 也不属于不合法ip地址,计数时请忽略
if(first == 0 || first == 127)
continue;
if (!judge_ip(mask) || !is_mask(mask))
err++;
else {
if (is_private(ip))
p++;
if (first >= 1 && first <= 126)
a++;
else if (first >= 128 && first <= 191)
b++;
else if (first >= 192 && first <= 223)
c++;
else if (first >= 224 && first <= 239)
d++;
else if (first >= 240 && first <= 255)
e++;
}
}
cout << a << " " << b << " " << c << " " << d << " " << e << " " << err << " "
<< p << endl;
return 0;
}
// 64 位输出请用 printf("%lld")
* HJ19 简单错误记录
描述
开发一个简单错误记录功能小模块,能够记录出错的代码所在的文件名称和行号。
处理:
1、 记录最多8条错误记录,循环记录,最后只用输出最后出现的八条错误记录。对相同的错误记录只记录一条,但是错误计数增加。最后一个斜杠后面的带后缀名的部分(保留最后16位)和行号完全匹配的记录才做算是“相同”的错误记录。
2、 超过16个字符的文件名称,只记录文件的最后有效16个字符;
3、 输入的文件可能带路径,记录文件名称不能带路径。也就是说,哪怕不同路径下的文件,如果它们的名字的后16个字符相同,也被视为相同的错误记录
4、循环记录时,只以第一次出现的顺序为准,后面重复的不会更新它的出现时间,仍以第一次为准
输入描述:
每组只包含一个测试用例。一个测试用例包含一行或多行字符串。每行包括带路径文件名称,行号,以空格隔开。
输出描述:
将所有的记录统计并将结果输出,格式:文件名 代码行数 数目,一个空格隔开
代码:
#include <iostream>
#include <string>
#include <map>
#include <deque>
using namespace std;
int main() {
string str;
map<string, int> cnt;
deque<string> dq;
while (getline(cin, str)) {
str = str.substr(str.find_last_of('\\') + 1);
int pos = str.find_last_of(' ');
if (pos > 16)
str = str.substr(pos - 16);
if (!cnt.count(str))
dq.push_back(str);
cnt[str]++;
// 只保留最后出现的八条错误记录
if (dq.size() > 8)
dq.pop_front();
}
for (auto s : dq)
cout << s << " " << cnt[s] << endl;
return 0;
}
// 64 位输出请用 printf("%lld")
HJ20 密码验证合格程序
描述
密码要求:
1.长度超过8位
2.包括大小写字母.数字.其它符号,以上四种至少三种
3.不能有长度大于2的包含公共元素的子串重复 (注:其他符号不含空格或换行)
输入描述:
一组字符串。
输出描述:
如果符合要求输出:OK,否则输出NG
代码:
#include <iostream>
#include <vector>
using namespace std;
string passwordVerification(const string& s) {
if (s.length() <= 8)
return "NG";
int n = s.length();
// lower, upper, digit, other
vector<bool> cnt(4, false);
for (const char& ch : s) {
if (islower(ch))
cnt[0] = true;
else if (isupper(ch))
cnt[1] = true;
else if (isdigit(ch))
cnt[2] = true;
else
cnt[3] = true;
}
int count = 0;
for (int i = 0; i < 4; i++)
if (cnt[i])
count++;
if (count < 3)
return "NG";
for (int i = 0; i <= n - 6; i++) {
string t1 = s.substr(i, 3);
for (int j = i + 3; j <= n - 3; j++) {
string t2 = s.substr(j, 3);
if (t1 == t2)
return "NG";
}
}
return "OK";
}
int main()
{
string pwd;
while (getline(cin, pwd)) {
cout << passwordVerification(pwd) << endl;
}
return 0;
}
// 64 位输出请用 printf("%lld")