华为机试真题练习汇总(81~90)
- 华为机试真题练习汇总(81~90)
-
- [HJ81 字符串字符匹配](#HJ81 字符串字符匹配)
- [** HJ82 将真分数分解为埃及分数](#** HJ82 将真分数分解为埃及分数)
- [HJ83 二维数组操作](#HJ83 二维数组操作)
- [HJ84 统计大写字母个数](#HJ84 统计大写字母个数)
- [HJ85 最长回文子串](#HJ85 最长回文子串)
- [HJ86 求最大连续bit数](#HJ86 求最大连续bit数)
- [HJ87 密码强度等级](#HJ87 密码强度等级)
- [* HJ88 扑克牌大小](#* HJ88 扑克牌大小)
- [* HJ89 24点运算](#* HJ89 24点运算)
- [HJ90 合法IP](#HJ90 合法IP)
华为机试真题练习汇总(81~90)
题目来源:华为机试 - 牛客
标记 * 号的代表有难度的题目。
HJ81 字符串字符匹配
描述
判断短字符串S中的所有字符是否在长字符串T中全部出现。
请注意本题有多组样例输入。
输入描述:
输入两个字符串。第一个为短字符串,第二个为长字符串。两个字符串均由小写字母组成。
输出描述:
如果短字符串的所有字符均在长字符串中出现过,则输出字符串"true"。否则输出字符串"false"。
代码:
cpp
#include <iostream>
#include <vector>
using namespace std;
// bool isSubStr(string& s1, string& s2) {
// int len1 = s1.length(), len2 = s2.length();
// for (int i = 0; i <= len2 - len1; i++)
// if (s2.substr(i, len1) == s1)
// return true;
// return false;
// }
bool isAllOccurred(const string& s1, const string& s2) {
vector<bool> dict1(26, false);
for (const char& c : s1)
dict1[c - 'a'] = true;
vector<bool> dict2(26, false);
for (const char& c : s2)
dict2[c - 'a'] = true;
for (int i = 0; i < 26; i++)
if (dict1[i] && !dict2[i])
return false;
return true;
}
int main() {
string s1, s2;
cin >> s1 >> s2;
if (isAllOccurred(s1, s2))
cout << "true" << endl;
else
cout << "false" << endl;
return 0;
}
// 64 位输出请用 printf("%lld")
** HJ82 将真分数分解为埃及分数
描述
分子为1的分数称为埃及分数。现输入一个真分数(分子比分母小的分数,叫做真分数),请将该分数分解为埃及分数。如:8/11 = 1/2+1/5+1/55+1/110。
注:真分数指分子小于分母的分数,分子和分母有可能gcd不为1!
如有多个解,请输出任意一个。
输入描述:
输入一个真分数,String型
输出描述:
输出分解后的string
代码:
cpp
#include <iostream>
using namespace std;
int main() {
// a/b = 1/(x+1) + 1/(x+1) * (a-y)/b
// 其中,x = b/a,y = b%a
long a, b; // 分别是分子分母
char op; // 除号
while (cin >> a >> op >> b) {
while (a != 1) { //直到最后的a为1
if (b % a == 0) { //先去掉公因子
b = b / a;
break;
}
//按照公式推算运算
long x = b / a;
long y = b % a;
cout << 1 << op << x + 1 << "+";
a -= y;
b *= x + 1;
}
cout << 1 << op << b << endl;
}
return 0;
}
// 64 位输出请用 printf("%lld")
HJ83 二维数组操作
描述
输入描述:
输入数据按下列顺序输入:
1 表格的行列值
2 要交换的两个单元格的行列值
3 输入要插入的行的数值
4 输入要插入的列的数值
5 输入要查询的单元格的坐标
输出描述:
输出按下列顺序输出:
1 初始化表格是否成功,若成功则返回0, 否则返回-1
2 输出交换单元格是否成功
3 输出插入行是否成功
4 输出插入列是否成功
5 输出查询单元格数据是否成功
代码:
cpp
#include <iostream>
using namespace std;
int main() {
int row, col; // 表格的行列值
while (cin >> row >> col) {
// 初始化表格是否成功,若成功则返回0, 否则返回-1
if (row > 0 && row <= 9 && col > 0 && col <= 9)
cout << 0 << endl;
else
cout << -1 << endl;
// 交换坐标
int x1, y1, x2, y2;
cin >> x1 >> y1 >> x2 >> y2;
if (x1 < 0 || x1 >= row || y1 < 0 || y1 >= col
|| x2 < 0 || x2 >= row || y2 < 0 || y2 >= col)
cout << -1 << endl;
else
cout << 0 << endl;
// 在第x行上方添加一行
int x;
cin >> x;
if (x < 0 || x >= row || row >= 9)
cout << -1 << endl;
else
cout << 0 << endl;
// 在第 y 列左边添加一列
int y;
cin >> y;
if (y < 0 || y >= col || col >= 9)
cout << -1 << endl;
else
cout << 0 << endl;
// 查找坐标为 (x,y) 的单元格的值
cin >> x >> y;
if (x < 0 || x >= row || y < 0 || y >= col)
cout << -1 << endl;
else
cout << 0 << endl;
}
return 0;
}
// 64 位输出请用 printf("%lld")
HJ84 统计大写字母个数
描述
找出给定字符串中大写字符(即'A'-'Z')的个数。
字符串中可能包含空格或其他字符。
输入描述:
对于每组样例,输入一行,代表待统计的字符串
输出描述:
输出一个整数,代表字符串中大写字母的个数
代码:
cpp
#include <cctype>
#include <iostream>
using namespace std;
int main() {
string s;
getline(cin, s);
int count = 0;
for (char& c : s)
if (isupper(c))
count++;
cout << count << endl;
return 0;
}
// 64 位输出请用 printf("%lld")
HJ85 最长回文子串
描述
给定一个仅包含小写字母的字符串,求它的最长回文子串的长度。
所谓回文串,指左右对称的字符串。
所谓子串,指一个字符串删掉其部分前缀和后缀(也可以不删)的字符串
输入描述:
输入一个仅包含小写字母的字符串
输出描述:
返回最长回文子串的长度
代码:
cpp
#include <iostream>
using namespace std;
int palindromeLength(string& s, int low, int high) {
while (low >= 0 && high < s.length() && s[low] == s[high]) {
low--;
high++;
}
int len = high - low - 1;
return len;
}
int main() {
string s;
cin >> s;
int maxLen = 1;
for (int i = 1; i < s.length() - 1; i++) {
int len1 = palindromeLength(s, i, i);
int len2 = palindromeLength(s, i, i + 1);
if (max(len1, len2) > maxLen)
maxLen = max(len1, len2);
}
cout << maxLen << endl;
return 0;
}
// 64 位输出请用 printf("%lld")
HJ86 求最大连续bit数
描述
求一个int类型数字对应的二进制数字中1的最大连续数,例如3的二进制为00000011,最大连续2个1
输入描述:
输入一个int类型数字
输出描述:
输出转成二进制之后连续1的个数
代码 1:
cpp
#include <iostream>
using namespace std;
int main() {
int n;
cin >> n;
int count = 0, max_count = 0;
while (n) {
if (n % 2 == 1) // 最后一位为1
count++;
else { // 遇到不为1
max_count = max(max_count, count); // 更新最大值
count = 0; // 重置
}
n /= 2; // 去掉最后一位
}
max_count = max(max_count, count); // 最后一次更新最大值
cout << max_count << endl;
return 0;
}
// 64 位输出请用 printf("%lld")
代码 2:
cpp
#include<iostream>
using namespace std;
int main() {
int n;
while (cin >> n) {
int count = 0;
for (; n != 0; count++) // 统计能够运算多少次
n &= n << 1; // 与自己左移一位后比较
cout << count << endl;
}
return 0;
}
// 64 位输出请用 printf("%lld")
HJ87 密码强度等级
描述
密码按如下规则进行计分,并根据不同的得分为密码进行安全等级划分。
一、密码长度:
5 分: 小于等于4 个字符
10 分: 5 到7 字符
25 分: 大于等于8 个字符
二、字母:
0 分: 没有字母
10 分: 密码里的字母全都是小(大)写字母
20 分: 密码里的字母符合"大小写混合"
三、数字:
0 分: 没有数字
10 分: 1 个数字
20 分: 大于1 个数字
四、符号:
0 分: 没有符号
10 分: 1 个符号
25 分: 大于1 个符号
五、奖励(只能选符合最多的那一种奖励):
2 分: 字母和数字
3 分: 字母、数字和符号
5 分: 大小写字母、数字和符号
最后的评分标准:
>= 90: 非常安全
>= 80: 安全(Secure)
>= 70: 非常强
>= 60: 强(Strong)
>= 50: 一般(Average)
>= 25: 弱(Weak)
>= 0: 非常弱(Very_Weak)
对应输出为:
VERY_SECURE
SECURE
VERY_STRONG
STRONG
AVERAGE
WEAK
VERY_WEAK
请根据输入的密码字符串,进行安全评定。
注:
字母:a-z, A-Z
数字:0-9
符号包含如下: (ASCII码表可以在UltraEdit的菜单view->ASCII Table查看)
!"#$%&'()*+,-./ (ASCII码:0x21~0x2F)
:;<=>?@ (ASCII码:0x3A~0x40)
[]^_` (ASCII码:0x5B~0x60)
{|}~ (ASCII码:0x7B~0x7E)
提示:
1 <= 字符串的长度<= 300
输入描述:
输入一个string的密码
输出描述:
输出密码等级
代码:
cpp
#include <algorithm>
#include <cctype>
#include <iostream>
using namespace std;
bool issignal(char& c) {
const string signalStr = "!\"#$%&'()*+,-./[\\]^_`{|}~";
if (find(signalStr.begin(), signalStr.end(), c) != signalStr.end())
return true;
else
return false;
}
int main() {
string pwd;
cin >> pwd;
int score = 0;
// 密码长度
int len = pwd.length();
if (len <= 4)
score += 5;
else if (len < 8)
score += 10;
else if (len >= 8)
score += 25;
// 统计字母、数字、符号
int lower = 0, upper = 0, digit = 0, signal = 0;
for (char& c : pwd) {
if (islower(c))
lower++;
else if (isupper(c))
upper++;
else if (isdigit(c))
digit++;
else if (issignal(c))
signal++;
}
// 字母
if ((lower > 0 && upper == 0) || (lower == 0 && upper > 0))
score += 10;
else if (lower > 0 && upper > 0)
score += 20;
if (digit == 1)
score += 10;
else if (digit > 1)
score += 20;
if (signal == 1)
score += 10;
else if (signal > 1)
score += 25;
int alpha = lower + upper;
if (lower > 0 && upper > 0 && digit > 0 && signal > 0)
score += 5;
else if (alpha > 0 && digit > 0 && signal > 0)
score += 3;
else if (alpha > 0 && digit > 0)
score += 2;
if (score >= 90)
cout << "VERY_SECURE" << endl;
else if (score >= 80)
cout << "SECURE" << endl;
else if (score >= 70)
cout << "VERY_STRONG" << endl;
else if (score >= 60)
cout << "STRONG" << endl;
else if (score >= 50)
cout << "AVERAGE" << endl;
else if (score >= 25)
cout << "WEAK" << endl;
else if (score >= 0)
cout << "VERY_WEAK" << endl;
return 0;
}
// 64 位输出请用 printf("%lld")
* HJ88 扑克牌大小
描述
扑克牌游戏大家应该都比较熟悉了,一副牌由54张组成,含3~A、2各4张,小王1张,大王1张。牌面从小到大用如下字符和字符串表示(其中,小写joker表示小王,大写JOKER表示大王):
3 4 5 6 7 8 9 10 J Q K A 2 joker JOKER
输入两手牌,两手牌之间用"-"连接,每手牌的每张牌以空格分隔,"-"两边没有空格,如:4 4 4 4-joker JOKER。
请比较两手牌大小,输出较大的牌,如果不存在比较关系则输出ERROR。
基本规则:
(1)输入每手牌可能是个子、对子、顺子(连续5张)、三个、炸弹(四个)和对王中的一种,不存在其他情况,由输入保证两手牌都是合法的,顺子已经从小到大排列;
(2)除了炸弹和对王可以和所有牌比较之外,其他类型的牌只能跟相同类型的存在比较关系(如,对子跟对子比较,三个跟三个比较),不考虑拆牌情况(如:将对子拆分成个子);
(3)大小规则跟大家平时了解的常见规则相同,个子、对子、三个比较牌面大小;顺子比较最小牌大小;炸弹大于前面所有的牌,炸弹之间比较牌面大小;对王是最大的牌;
(4)输入的两手牌不会出现相等的情况。
输入描述:
输入两手牌,两手牌之间用"-"连接,每手牌的每张牌以空格分隔,"-"两边没有空格,如 4 4 4 4-joker JOKER。
输出描述:
输出两手牌中较大的那手,不含连接符,扑克牌顺序不变,仍以空格隔开;如果不存在比较关系则输出ERROR。
代码:
cpp
#include <algorithm>
#include <iostream>
using namespace std;
int getValue(string& s) {
if (s == "joker")
return 14;
if (s == "JOKER")
return 15;
switch (s[0]) {
case '3':
return 1;
case '4':
return 2;
case '5':
return 3;
case '6':
return 4;
case '7':
return 5;
case '8':
return 6;
case '9':
return 7;
case '1':
return 8; // 用1代替10
case 'J':
return 9;
case 'Q':
return 10;
case 'K':
return 11;
case 'A':
return 12;
case '2':
return 13;
}
return 0;
}
int main() {
string input;
getline(cin, input);
int split_idx = find(input.begin(), input.end(), '-') - input.begin();
string s1 = input.substr(0, split_idx); // 从'-'处截取成两段
string s2 = input.substr(split_idx + 1);
// 如果有王炸直接输出王炸
if (s1 == "joker JOKER" || s2 == "joker JOKER") {
cout << "joker JOKER" << endl;
return 0;
}
// 统计字符串中空格的数量
int space1 = 0, space2 = 0;
for (char& c : s1)
if (c == ' ')
space1++;
for (char& c : s2)
if (c == ' ')
space2++;
// 输入每手牌可能是个子、对子、顺子(连续5张)、三个、炸弹(四个)和对王中的一种,不存在其他情况
if (space1 == 3 && space2 == 3) {
// 都是炸弹
if (getValue(s1) > getValue(s2)) // 比较炸弹大小
cout << s1 << endl;
else
cout << s2 << endl;
} else if (space1 == 3) // 字符串其中一个是炸弹,输出炸弹
cout << s1 << endl;
else if (space2 == 3)
cout << s2 << endl;
else if (space1 == space2) { // 没有炸弹的情况下相同类型才能比较
if (getValue(s1) > getValue(
s2)) // 个子、对子、三个、顺子都是比较第一个大小
cout << s1 << endl;
else
cout << s2 << endl;
} else // 无法比较
cout << "ERROR" << endl;
return 0;
}
// 64 位输出请用 printf("%lld")
* HJ89 24点运算
描述
计算24点是一种扑克牌益智游戏,随机抽出4张扑克牌,通过加(+),减(-),乘(*), 除(/)四种运算法则计算得到整数24,本问题中,扑克牌通过如下字符或者字符串表示,其中,小写joker表示小王,大写JOKER表示大王:
3 4 5 6 7 8 9 10 J Q K A 2 joker JOKER
本程序要求实现:输入4张牌,输出一个算式,算式的结果为24点。
详细说明:
1.运算只考虑加减乘除运算,没有阶乘等特殊运算符号,没有括号,友情提醒,整数除法要当心,是属于整除,比如2/3=0,3/2=1;
2.牌面2~10对应的权值为2~10, J、Q、K、A权值分别为为11、12、13、1;
3.输入4张牌为字符串形式,以一个空格隔开,首尾无空格;如果输入的4张牌中包含大小王,则输出字符串"ERROR",表示无法运算;
4.输出的算式格式为4张牌通过±/四个运算符相连,中间无空格,4张牌出现顺序任意,只要结果正确;
5.输出算式的运算顺序从左至右,不包含括号,如1+2+3 4的结果为24,2 A 9 A不能变为(2+1)*(9-1)=24
6.如果存在多种算式都能计算得出24,只需输出一种即可,如果无法得出24,则输出"NONE"表示无解。
7.因为都是扑克牌,不存在单个牌为0的情况,且没有括号运算,除数(即分母)的数字不可能为0
数据范围:一行由4张牌组成的字符串
输入描述:
输入4张牌为字符串形式,以一个空格隔开,首尾无空格;
输出描述:
输出怎么运算得到24,如果无法得出24,则输出"NONE"表示无解,如果输入的4张牌中包含大小王,则输出字符串"ERROR",表示无法运算;
代码:
cpp
#include <algorithm>
#include <iostream>
#include <unordered_map>
#include <vector>
using namespace std;
unordered_map<string, int> CardtoNum = {{"A", 1}, {"2", 2}, {"3", 3}, {"4", 4}, {"5", 5}, {"6", 6},
{"7", 7}, {"8", 8}, {"9", 9}, {"10", 10}, {"J", 11}, {"Q", 12}, {"K", 13}
}; //输入的字符映射到数字
unordered_map<int, string> NumtoCard = {{1, "A"}, {2, "2"}, {3, "3"}, {4, "4"}, {5, "5"}, {6, "6"},
{7, "7"}, {8, "8"}, {9, "9"}, {10, "10"}, {11, "J"}, {12, "Q"}, {13, "K"}
}; //返回的数字映射到字符
const vector<char> Op = {'+', '-', '*', '/'};
int cal(int a, int b, int op) {
switch (op) {
case 0:
return a + b;
case 1:
return a - b;
case 2:
return a * b;
case 3:
return a / b;
}
return 0;
}
bool cal24(vector<int>& a, vector<int>& op) {
int res = cal(a[0], a[1], op[0]);
for (int i = 1; i < 3; i++)
res = cal(res, a[i + 1], op[i]);
return res == 24;
}
void printFormula(vector<int>& nums, vector<int>& op) {
for (int i = 0; i < 3; i++)
cout << NumtoCard[nums[i]] << Op[op[i]];
cout << NumtoCard[nums[3]] << endl;
}
int main() {
vector<string> s(4);
for (int i = 0; i < 4; i++)
cin >> s[i];
vector<int> nums(4);
for (int i = 0; i < 4; i++) {
if (s[i] == "joker" || s[i] == "JOKER") { // 遇到大小王
cout << "ERROR" << endl;
return 0;
}
nums[i] = CardtoNum[s[i]]; // 字符串转数字
}
sort(nums.begin(), nums.end());
bool flag = false;
vector<int> op(4);
do {
// 枚举三个符号的所有情况
for (int i = 0; i < 4 && !flag; i++) {
op[0] = i;
for (int j = 0; j < 4 && !flag; j++) {
op[1] = j;
for (int k = 0; k < 4 && !flag; k++) {
op[2] = k;
if (cal24(nums, op)) { // 符合条件
printFormula(nums, op);
flag = true; // 找到了,准备跳出所有循环
}
}
}
}
} while (next_permutation(nums.begin(), nums.end()) && !flag);
if (!flag)
cout << "NONE" << endl;
return 0;
}
// 64 位输出请用 printf("%lld")
HJ90 合法IP
描述
IPV4地址可以用一个32位无符号整数来表示,一般用点分方式来显示,点将IP地址分成4个部分,每个部分为8位,表示成一个无符号整数(因此正号不需要出现),如10.137.17.1,是我们非常熟悉的IP地址,一个IP地址串中没有空格出现(因为要表示成一个32数字)。
现在需要你用程序来判断IP是否合法。
输入描述:
输入一个ip地址,保证不包含空格
输出描述:
返回判断的结果YES or NO
代码:
cpp
#include <cctype>
#include <iostream>
#include <vector>
#include <sstream>
using namespace std;
bool judge_ip(string& s) {
vector<int> addr;
stringstream ss(s);
string seg;
while (getline(ss, seg, '.')) {
if (seg.empty())
return false;
if (seg.length() > 1 && (!isdigit(seg[0]) || seg[0] == '0'))
return false;
addr.push_back(stoi(seg));
}
if (addr.size() != 4)
return false;
for (int& a : addr)
if (a < 0 || a > 255)
return false;
return true;
}
int main() {
string ip;
cin >> ip;
if (judge_ip(ip))
cout << "YES" << endl;
else
cout << "NO" << endl;
return 0;
}
// 64 位输出请用 printf("%lld")