华为机试真题练习汇总(91~100)
华为机试真题练习汇总(91~100)
题目来源:华为机试 - 牛客
标记 * 号的代表有难度的题目。
HJ91 走方格的方案数
描述
请计算n*m的棋盘格子(n为横向的格子数,m为竖向的格子数)从棋盘左上角出发沿着边缘线从左上角走到右下角,总共有多少种走法,要求不能走回头路,即:只能往右和往下走,不能往左和往上走。
注:沿棋盘格之间的边缘线行走
输入描述:
输入两个正整数n和m,用空格隔开。(1≤n,m≤8)
输出描述:
输出一行结果
代码:
#include <iostream>
#include <vector>
using namespace std;
int main() {
int n, m;
cin >> n >> m;
// 状态矩阵
vector<vector<int>> dp(n + 1, vector<int>(m + 1, 1));
// 初始化
for (int i = 0; i <= n; i++)
dp[i][0] = 1;
for (int j = 0; j <= m; j++)
dp[0][j] = 1;
// 状态转移
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++) {
dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
}
cout << dp[n][m] << endl;
return 0;
}
// 64 位输出请用 printf("%lld")
HJ92 在字符串中找出连续最长的数字串
描述
输入一个字符串,返回其最长的数字子串,以及其长度。若有多个最长的数字子串,则将它们全部输出(按原字符串的相对位置)
本题含有多组样例输入。
输入描述:
输入一个字符串。1<=len(字符串)<=200
输出描述:
输出字符串中最长的数字字符串和它的长度,中间用逗号间隔。如果有相同长度的串,则要一块儿输出(中间不要输出空格)。
代码:
#include <cctype>
#include <iostream>
#include <utility>
#include <vector>
using namespace std;
int main() {
string s;
while (cin >> s) {
vector<string> digitStr;
int maxLen = 0;
int i = 0;
while (i < s.length()) {
if (isdigit(s[i])) {
int j = i + 1;
while (isdigit(s[j]) && j < s.length())
j++;
// s[i,j-1] 是一个数字子串
string d = s.substr(i, j - i);
digitStr.push_back(d);
maxLen = max(maxLen, (int)d.length());
i = j + 1;
} else {
i++;
}
}
for (string& d : digitStr)
if (d.length() == maxLen)
cout << d;
cout << "," << maxLen << endl;
}
return 0;
}
// 64 位输出请用 printf("%lld")
HJ93 数组分组
描述
输入int型数组,询问该数组能否分成两组,使得两组中各元素加起来的和相等,并且,所有5的倍数必须在其中一个组中,所有3的倍数在另一个组中(不包括5的倍数),不是5的倍数也不是3的倍数能放在任意一组,可以将数组分为空数组,能满足以上条件,输出true;不满足时输出false。
输入描述:
第一行是数据个数,第二行是输入的数据
输出描述:
返回true或者false
代码:
#include <iostream>
#include <numeric>
#include <unordered_set>
#include <vector>
using namespace std;
int main() {
int n;
cin >> n;
vector<int> other;
int sum5 = 0, sum3 = 0;
for (int i = 0; i < n; i++) {
int x;
cin >> x;
if (x % 5 == 0)
sum5 += x;
else if (x % 3 == 0)
sum3 += x;
else
other.push_back(x);
}
// 枚举所有组合的不重复和
unordered_set<int> s;
s.insert(0); // 0 代表空数组
for (int& x : other) {
unordered_set<int> tmp(s);
for (auto it : tmp)
s.insert(it + x);
}
bool found = false;
int sum = accumulate(other.begin(), other.end(), 0);
for (auto it : s)
if (it + sum3 == sum5 + sum - it) {
found = true;
break;
}
cout << (found ? "true" : "false") << endl;
return 0;
}
// 64 位输出请用 printf("%lld")
HJ94 记票统计
描述
请实现一个计票统计系统。你会收到很多投票,其中有合法的也有不合法的,请统计每个候选人得票的数量以及不合法的票数。
(注:不合法的投票指的是投票的名字不存在n个候选人的名字中!!)
输入描述:
第一行输入候选人的人数n,第二行输入n个候选人的名字(均为大写字母的字符串),第三行输入投票人的人数,第四行输入投票。
输出描述:
按照输入的顺序,每行输出候选人的名字和得票数量(以" : "隔开,注:英文冒号左右两边都有一个空格!),最后一行输出不合法的票数,格式为"Invalid : "+不合法的票数。
代码:
#include <iostream>
#include <set>
#include <unordered_map>
#include <vector>
using namespace std;
int main() {
int n;
cin >> n;
vector<string> list;
set<string> s;
for (int i = 0; i < n; i++) {
string name;
cin >> name;
list.push_back(name);
s.insert(name);
}
int m;
cin >> m;
int valid = 0;
unordered_map<string, int> mp;
for (int i = 0; i < m; i++) {
string name;
cin >> name;
if (s.count(name)) {
mp[name]++;
valid++;
}
}
// print
for (auto& name : list)
cout << name << " : " << mp[name] << endl;
cout << "Invalid : " << m - valid << endl;
return 0;
}
// 64 位输出请用 printf("%lld")
HJ95 人民币转换
描述
考试题目和要点:
1、中文大写金额数字前应标明“人民币”字样。中文大写金额数字应用壹、贰、叁、肆、伍、陆、柒、捌、玖、拾、佰、仟、万、亿、元、角、分、零、整等字样填写。
2、中文大写金额数字到“元”为止的,在“元”之后,应写“整字,如532.00应写成“人民币伍佰叁拾贰元整”。在”角“和”分“后面不写”整字。
3、阿拉伯数字中间有“0”时,中文大写要写“零”字,阿拉伯数字中间连续有几个“0”时,中文大写金额中间只写一个“零”字,如6007.14,应写成“人民币陆仟零柒元壹角肆分“。
4、10应写作“拾”,100应写作“壹佰”。例如,1010.00应写作“人民币壹仟零拾元整”,110.00应写作“人民币壹佰拾元整”
5、十万以上的数字接千不用加“零”,例如,30105000.00应写作“人民币叁仟零拾万伍仟元整”
输入描述:
输入一个double数
输出描述:
输出人民币格式
代码:
#include <iostream>
using namespace std;
// 构建个位的字典(数组)
const string gewei[10] = {"零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"};
// 获取元钱的函数接口,即小数点之前的部分
void Get_Before_Plot(string str) {
if (str == "0") {
return;
}
for (int i = str.size() - 1, j = 0; i >= 0; i--, j++) {
// i表示这是数字的第几位,j表示字符串下标
if (str[j] != '0') { // 将当前位置的数字转为中文
if (!(str[j] == '1' && i % 4 == 1)) // 10应写作“拾”,而不是“壹零”
cout << gewei[str[j] - '0'];
}
if (i != 0) { // 当前不是个位
if (i % 8 == 0 && i >= 8) { // 亿位
cout << "亿";
}
if (i % 4 == 0 && i % 8 != 0) { // 万位
cout << "万";
if (str[j + 1] == '0') // 如果千位为0
cout << "零";
}
if (i % 4 == 3 && str[j] != '0') { // 千
cout << "仟";
if (str[j + 1] == '0' && str[j + 2] != '0') // 百位为0
cout << "零";
}
if (i % 4 == 2 && str[j] != '0') { //百
cout << "佰";
if (str[j + 1] == '0' && str[j + 2] != '0') // 十位为0
cout << "零";
}
if (i % 4 == 1 && str[j] != '0') // 十位
cout << "拾";
}
}
return;
}
// 获取角分零钱的函数接口,即小数点之后的部分
void Get_After_Plot(string str) {
if (str == "00") {
cout << "整";
return;
}
if (str[0] > '0') {
cout << gewei[str[0] - '0'] << "角";
}
if (str[1] > '0') {
cout << gewei[str[1] - '0'] << "分";
}
return;
}
int main() {
string money;
cin >> money;
//
string str1 = money.substr(0, money.find('.'));
// 获取小数点后的子字符串
string str2 = money.substr(money.find('.') + 1);
// 输出人民币
cout << "人民币";
// 输出元钱
Get_Before_Plot(str1);
if (str1 != "0")
cout << "元";
// 输出角分零钱
Get_After_Plot(str2);
// 换行
cout << endl;
}
// 64 位输出请用 printf("%lld")
HJ96 表示数字
描述
将一个字符串中所有的整数前后加上符号“*”,其他字符保持不变。连续的数字视为一个整数。
输入描述:
输入一个字符串。
输出描述:
字符中所有出现的数字前后加上符号“*”,其他字符保持不变。
代码:
#include <cctype>
#include <iostream>
using namespace std;
int main() {
string input;
cin >> input;
bool flag = false;
for (char& c : input) {
if (isdigit(c)) {
if (flag == false) {
// 进入数字子串
cout << '*';
flag = true;
}
cout << c;
} else {
if (flag == true) {
// 退出数字子串
cout << '*';
flag = false;
}
cout << c;
}
}
if (isdigit(input[input.length() - 1]))
cout << '*';
return 0;
}
// 64 位输出请用 printf("%lld")
HJ97 记负均正
描述
首先输入要输入的整数个数n,然后输入n个整数。输出为n个整数中负数的个数,和所有正整数的平均值,结果保留一位小数。
0即不是正整数,也不是负数,不计入计算。如果没有正数,则平均值为0。
输入描述:
首先输入一个正整数n,
然后输入n个整数。
输出描述:
输出负数的个数,和所有正整数的平均值。
代码:
#include <cstdio>
#include <iostream>
using namespace std;
int main() {
int n;
cin >> n;
int cnt_neg = 0, sum = 0, cnt_pos = 0;
for (int i = 0; i < n; i++) {
int x;
cin >> x;
if (x > 0) {
sum += x;
cnt_pos++;
} else if (x < 0)
cnt_neg++;
}
cout << cnt_neg << " ";
if (cnt_pos) {
double avg = 1.0 * sum / cnt_pos;
printf("%.1f\n", avg);
} else
cout << "0.0" << endl;
return 0;
}
// 64 位输出请用 printf("%lld")
HJ98 自动售货系统
链接:https://www.nowcoder.com/practice/cd82dc8a4727404ca5d32fcb487c50bf
代码:
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
#include<sstream>
using namespace std;
const vector<int> price = {2, 3, 4, 5, 8, 6}; // 商品价格
int money = 0; //投入的钱
// 通过字符c分割字符串
vector<string> split(string str, const char c) {
vector<string> res;
istringstream iss(str); // 字符串流输入
string temp = "";
while (getline(iss, temp, c)) // 根据流输入分割
res.push_back(temp);
return res;
}
// 初始化函数
void init(vector<int>& a, vector<int>& b, string& s) {
money = 0; // 初始化投入的钱
s = s.substr(2, s.length() - 2); // 去掉前面的r和空格
a[0] = a[1] = a[2] = a[3] = a[4] = a[5] = 0;
b[0] = b[1] = b[2] = b[3] = 0;
int i = 0;
// 判别是前面部分商品价格还是后面部分零钱盒
bool flag = false;
for (auto c : s) {
if (isdigit(c) && !flag) // 数字且是价格
a[i] = a[i] * 10 + (c - ' 0'); // 根据字符计算数字
else if (isdigit(c) && flag) //数字且是零钱
b[i] = b[i] * 10 + (c - '0'); // 根据字符计算数字
else if (c == ' ') { // 遇到空格换成零钱
flag = true;
i = 0;
} else if (c == '-') // 遇到-后移一位商品或零钱
i++;
}
cout << "S001:Initialization is successful" << endl;
}
// 投币函数
void pay(vector<int>& a, vector<int>& b, string& s) {
int num = 0;
for (auto& c : s)
if (isdigit(c)) // 只计算数字部分
num = num * 10 + (c - '0'); // 一次只投一张
if (num == 1 || num == 2 || num == 5 || num == 10) { // 投入合法的币种
if (num > 2 && num > (b[0] + b[1] * 2)) {
// 存钱盒中1元和2元面额钱币总额小于本次投入的钱币面额
cout << "E003:Change is not enough, pay fail" << endl;
} else if ((a[0] || a[1] || a[2] || a[3] || a[4] || a[5]) == 0) {
// 商品全部为0
cout << "E005:All the goods sold out" << endl;
} else {
//零钱盒中钱数增加
if (num == 1 || num == 2)
b[num - 1]++;
else if (num == 5)
b[2]++;
else b[3]++;
money += num; // 投入的总钱数增加
cout << "S002:Pay success,balance=" << money << endl;
}
} else {
// 不合法币种
cout << "E002:Denomination error" << endl;
}
}
// 购买函数
void buy(vector<int>& a, vector<int>& b, string& s) {
// 检查命令是否是4位,第三位是否为A,第四位是否数字1-6
if (s.length() == 4 && (s[2] == 'A') && (s[3] - '0' < 7) && isdigit(s[3]) &&
(s[3] != '0')) {
if (a[s[3] - '1'] == 0) {
// 该商品的售罄
cout << "E007:The goods sold out" << endl;
} else if (price[s[3] - '1'] > money) {
// 该商品价格大于投入的钱
cout << "E008:Lack of balance" << endl;
} else { // 成功购买
money -= price[s[3] - '1']; // 投入的钱要减去买的商品
a[s[3] - '1']--;
cout << "S003:Buy success,balance=" << money << endl;
}
} else {
// 输入命令不合法,商品不存在
cout << "E006:Goods does not exist" << endl;
}
}
// 退币函数
void back(vector<int>& coins) {
int a = 0, b = 0, c = 0, d = 0; // 四个币种
if (money == 0) {
// 投入的没有钱了,不用退
cout << "E009:Work failure" << endl;
} else {
d = money / 10; // 优先退大币额的数量
if (d <= coins[3]) { // 10块的钱够退
money = money % 10;
coins[3] -= d;
} else { // 10块的钱不够退
d = coins[3]; // 全部退完
coins[3] = 0;
money -= d * 10; // 剩余要退的
}
c = money / 5; // 再计算要退的5块钱的数量
if (c <= coins[2]) { // 5块的钱够退
money = money % 5;
coins[2] -= c;
} else { // 5块的钱不够退
c = coins[2]; // 全部退完
coins[2] = 0;
money -= d * 5; // 剩余要退的
}
b = money / 2; // 再计算要退的2块钱的数量
if (b <= coins[1]) { // 2块的钱够退
money = money % 2;
coins[1] -= b;
} else { // 2块的钱不够退
b = coins[1]; // 全部退完
coins[1] = 0;
money -= d * 2; // 剩余要退的
}
a = money; // 再计算要退的1块钱的数量
if (a <= coins[0]) { // 1块的钱够退
coins[0] -= a;
money = 0;
} else { // 1块的钱不够退
coins[0] = 0;
money -= a;
}
cout << "1 yuan coin number=" << a << endl;
cout << "2 yuan coin number=" << b << endl;
cout << "5 yuan coin number=" << c << endl;
cout << "10 yuan coin number=" << d << endl;
}
}
// 重载比较
bool cmp(pair<pair<string, int>, int>& a, pair<pair<string, int>, int>& b) {
if (a.second != a.second) // 优先比较商品数量
return a.second > b.second;
else //再比较商品名字
return a.first.first < b.first.first;
}
// 查询函数
void query(vector<int>& a, vector<int>& b, string& s) {
if (s[1] == ' ' && s.length() == 3) { // 检查查询命令的合法性
if (s[2] == 0) { // 类别为0
vector<pair<pair<string, int>, int> > temp;
for (int i = 0; i < 6; i++) {
// 商品信息入vector方便排序输出
temp.push_back(make_pair(make_pair("A" + char(i + 1), price[i]), a[i]));
}
sort(temp.begin(), temp.end(), cmp); // 按照重载后的比较排序
// 输出
for (int i = 0; i < 6; i++)
cout << temp[i].first.first << " " << temp[i].first.second << " " <<
temp[i].second << endl;
} else if (s[2] == 1) { // 类别为1
cout << "1 yuan coin number=" << b[0] << endl
<< "2 yuan coin number=" << b[1] << endl
<< "5 yuan coin number=" << b[2] << endl
<< "10 yuan coin number=" << b[3] << endl;
} else
cout << "E010:Parameter error" << endl;
} else
cout << "E010:Parameter error" << endl;
}
int main()
{
string s;
vector<int> goods(6, 0);
vector<int> coins(4, 0);
while (getline(cin, s)) {
vector<string> orders = split(s, ';');
for (auto c : orders) {
switch (c[0]) {
case 'r': // 初始化
init(goods, coins, c);
break;
case 'p': // 投币
pay(goods, coins, c);
break;
case 'b': // 购买商品
buy(goods, coins, c);
break;
case 'c': // 退币
back(coins);
break;
case 'q': // 查询
query(goods, coins, c);
break;
}
}
}
return 0;
}
// 64 位输出请用 printf("%lld")
HJ99 自守数
描述
自守数是指一个数的平方的尾数等于该数自身的自然数。例如:25^2 = 625,76^2 = 5776,9376^2 = 87909376。请求出n(包括n)以内的自守数的个数。
输入描述:
int型整数
输出描述:
n以内自守数的数量。
代码:
#include <iostream>
using namespace std;
bool isSelfNum(int x) {
string s1 = to_string(x), s2 = to_string(x * x);
return s1 == s2.substr(s2.length() - s1.length());
}
int main() {
int n;
cin >> n;
int count = 0;
for (int i = 0; i <= n; i++)
if (isSelfNum(i))
count++;
cout << count << endl;
return 0;
}
// 64 位输出请用 printf("%lld")
HJ100 等差数列
描述
等差数列 2,5,8,11,14。。。。
(从 2 开始的 3 为公差的等差数列)
输出求等差数列前n项和。
输入描述:
输入一个正整数n。
输出描述:
输出一个相加后的整数。
代码:
#include <iostream>
using namespace std;
int main() {
int n;
cin >> n;
int begin = 2, end = 2 + 3 * (n - 1);
cout << (begin + end)*n / 2 << endl;
return 0;
}
// 64 位输出请用 printf("%lld")