华为机试真题练习汇总(41~50)
- 华为机试真题练习汇总(41~50)
- * HJ41 称砝码
- * HJ42 学英语
- * HJ43 迷宫问题
- * HJ44 Sudoku
- HJ45 名字的漂亮度
- HJ46 截取字符串
- HJ48 从单向链表中删除指定值的节点
- ** HJ50 四则运算
华为机试真题练习汇总(41~50)
题目来源:华为机试 - 牛客
标记 * 号的代表有难度的题目。
* HJ41 称砝码
描述
现有n种砝码,重量互不相等,分别为 m1,m2,m3…mn ;
每种砝码对应的数量为 x1,x2,x3…xn 。现在要用这些砝码去称物体的重量(放在同一侧),问能称出多少种不同的重量。
注:称重重量包括 0
输入描述:
对于每组测试数据:
第一行:n — 砝码的种数(范围[1,10])
第二行:m1 m2 m3 … mn — 每种砝码的重量(范围[1,2000])
第三行:x1 x2 x3 … xn — 每种砝码对应的数量(范围[1,10])
输出描述:
利用给定的砝码可以称出的不同的重量数
代码 1:
#include <iostream>
#include <unordered_set>
#include <vector>
using namespace std;int main() {int n;cin >> n;vector<int> weight(n), num(n);for (int i = 0; i < n; i++)cin >> weight[i];for (int i = 0; i < n; i++)cin >> num[i];unordered_set<int> s; // 集合用于去重s.insert(0); // 0也是一种for (int i = 0; i < n; i++) { // 对于每一种砝码for (int j = 1; j <= num[i]; j++) { // 用完之前数量之前unordered_set<int> temp(s);for (auto iter = temp.begin(); iter != temp.end(); iter++)s.insert(*iter + weight[i]);}}cout << s.size() << endl;return 0;
}
// 64 位输出请用 printf("%lld")
代码 2:
#include <iostream>
#include <unordered_set>
#include <vector>
using namespace std;int main() {int n;cin >> n;int max_weight = 0;vector<int> weight(n), num(n);for (int i = 0; i < n; i++)cin >> weight[i];for (int i = 0; i < n; i++) {cin >> num[i];max_weight += num[i] * weight[i];}// unordered_set<int> s;// s.insert(0);// for (int i = 0; i < n; i++)// for (int j = 1; j <= num[i]; j++) {// unordered_set<int> temp(s);// for (auto it = temp.begin(); it != temp.end(); it++)// s.insert(*it + weight[i]);// }// cout << s.size() << endl;// dp[i]: 能否称出质量为 i 的砝码vector<bool> dp(max_weight + 1, false);// 初始化dp[0] = true;for (int i = 0; i < n; i++)for (int j = 1; j <= num[i]; j++)for (int k = max_weight; k >= weight[i]; k--)if (dp[k - weight[i]] == true)dp[k] = true;int count = 0;for (int i = 0; i <= max_weight; i++)if (dp[i] == true)count++;cout << count << endl;return 0;
}
// 64 位输出请用 printf("%lld")
* HJ42 学英语
描述
Jessi初学英语,为了快速读出一串数字,编写程序将数字转换成英文:
具体规则如下:
1.在英语读法中三位数字看成一整体,后面再加一个计数单位。从最右边往左数,三位一单位,例如12,345 等
2.每三位数后记得带上计数单位 分别是thousand, million, billion.
3.公式:百万以下千以上的数 X thousand X, 10亿以下百万以上的数:X million X thousand X, 10 亿以上的数:X billion X million X thousand X. 每个X分别代表三位数或两位数或一位数。
4.在英式英语中百位数和十位数之间要加and,美式英语中则会省略,我们这个题目采用加上and,百分位为零的话,这道题目我们省略and
下面再看几个数字例句:
22: twenty two
100: one hundred
145: one hundred and forty five
1,234: one thousand two hundred and thirty four
8,088: eight thousand (and) eighty eight (注:这个and可加可不加,这个题目我们选择不加)
486,669: four hundred and eighty six thousand six hundred and sixty nine
1,652,510: one million six hundred and fifty two thousand five hundred and ten
说明:
数字为正整数,不考虑小数,转化结果为英文小写;
保证输入的数据合法
关键字提示:and,billion,million,thousand,hundred。
代码 1:
#include <iostream>
#include <vector>
using namespace std;vector<string> ones = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" };
vector<string> tens = { "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen" };
vector<string> twenties = { "zero", "ten", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety" };
vector<string> hundreds = { "hundred", "thousand", "million", "billion" };
vector<int> ihundreds = { (int)1e2, (int)1e3, (int)1e6, (int)1e9, (int)1e12 };string itostr(int n) {if (n <= 9)return ones[n];else if (n < 20)return tens[n % 10];else if (n < 1e2)return twenties[n / 10] + (n % 10 ? " " + ones[n % 10] : "");else {for (int i = 0; i < 4; i++)if (n < ihundreds[i + 1])return itostr(n / ihundreds[i]) + " "+ hundreds[i]+ (n % ihundreds[i] ? (i ? " " : " and ")+ itostr(n % ihundreds[i]) : "");}return "";
}int main() {int n;cin>>n;cout<<itostr(n)<<endl;return 0;
}
// 64 位输出请用 printf("%lld")
代码 2:
#include <iostream>
#include <map>
#include <string>
#include <vector>
using namespace std;map<int, string> u10 = {{1, "one"},{2, "two"},{3, "three"},{4, "four"},{5, "five"},{6, "six"},{7, "seven"},{8, "eight"},{9, "nine"}};map<int, string> u20 = {{10, "ten"},{11, "eleven"},{12, "twelve"},{13, "thirteen"},{14, "fourteen"},{15, "fifteen"},{16, "sixteen"},{17, "seventeen"},{18, "eighteen"},{19, "nineteen"}};map<int, string> u100 = {{2, "twenty"},{3, "thirty"},{4, "forty"},{5, "fifty"},{6, "sixty"},{7, "seventy"},{8, "eighty"},{9, "ninety"}};void getResult(vector<string>& result, int& num) {bool hundredSign = false;bool tenSign = false;if (num >= 100) {hundredSign = true;result.push_back(u10[num / 100]);result.push_back("hundred");num %= 100;}if (num >= 10) {tenSign = true;if (hundredSign) {result.push_back("and");}if (num <= 19) {result.push_back(u20[num]);num = 0;} else {result.push_back(u100[num / 10]);num %= 10;}}if (num > 0) {if (hundredSign && !tenSign) {result.push_back("and");}result.push_back(u10[num]);}
}int main() {long num;cin >> num;vector<string> result;int numMillion = num / 1000000;if (numMillion > 0) {getResult(result, numMillion);result.push_back("million");}int numThousand = num % 1000000 / 1000;if (numThousand > 0) {getResult(result, numThousand);result.push_back("thousand");}int numOne = num % 1000000 % 1000;if (numOne > 0) {getResult(result, numOne);}for (auto s : result) {cout << s << " ";}cout << endl;return 0;
}
* HJ43 迷宫问题
描述
定义一个二维数组 N*M ,如 5 × 5 数组下所示:
int maze[5][5] = {
0, 1, 0, 0, 0,
0, 1, 1, 1, 0,
0, 0, 0, 0, 0,
0, 1, 1, 1, 0,
0, 0, 0, 1, 0,
};
它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,要求编程序找出从左上角到右下角的路线。入口点为[0,0],既第一格是可以走的路。
输入描述:
输入两个整数,分别表示二维数组的行数,列数。再输入相应的数组,其中的1表示墙壁,0表示可以走的路。数据保证有唯一解,不考虑有多解的情况,即迷宫只有一条通道。
输出描述:
左上角到右下角的最短路径,格式如样例所示。
代码:
#include <functional>
#include <iostream>
#include <vector>
using namespace std;const int dx[] = {0, 0, 1, -1};
const int dy[] = {1, -1, 0, 0};int main() {int n, m;cin >> n >> m;vector<vector<int>> grid(n, vector<int>(m, 0));for (int i = 0; i < n; i++)for (int j = 0; j < m; j++)cin >> grid[i][j];vector<pair<int, int>> res, path;function<void(int, int)> dfs = [&](int i, int j) {if (i < 0 || i >= n || j < 0 || j >= m)return;if (grid[i][j])return;path.push_back(make_pair(i, j)); // 记入路径grid[i][j] = 1;if (i == n - 1 && j == m - 1) {res = path;return;}// 四个方向搜索for (int k = 0; k < 4; k++)dfs(i + dx[k], j + dy[k]);// 回溯path.pop_back();grid[i][j] = 0;};dfs(0, 0);for (auto& p : res)cout << "(" << p.first << "," << p.second << ")" << endl;return 0;
}
// 64 位输出请用 printf("%lld")
* HJ44 Sudoku
描述
问题描述:数独(Sudoku)是一款大众喜爱的数字逻辑游戏。玩家需要根据9X9盘面上的已知数字,推算出所有剩余空格的数字,并且满足每一行、每一列、每一个3X3粗线宫内的数字均含1-9,并且不重复。
输入描述:
包含已知数字的9X9盘面数组[空缺位以数字0表示]
输出描述:
完整的9X9盘面数组
代码:
#include <iostream>
using namespace std;int num[9][9]; // 用于保存9x9盘面
bool flag = false; // flag为true时表示推算完成,结束递归// 判断当前位置的值是否满足条件
bool check(int n) {int h = n / 9; // 行号int l = n % 9; // 列号// 同一列中不能有重复for (int i = 0; i < 9; ++i) {if (i != h && num[i][l] == num[h][l]) {return false;}}// 同一行中不能有重复for (int j = 0; j < 9; ++j) {if (j != l && num[h][j] == num[h][l]) {return false;}}// 九宫格内不重复for (int i = h / 3 * 3; i < h / 3 * 3 + 3; ++i) {for (int j = l / 3 * 3; j < l / 3 * 3 + 3; ++j) {if ((i != h || j != l) && num[i][j] == num[h][l]) {return false;}}}return true;
}void dfs(int n) {// 如果已经递归到右下角,输出整个盘面,并置flag为true,结束递归if (n == 81) {for (int i = 0; i < 9; ++i) {for (int j = 0; j < 8; ++j) {cout << num[i][j] << ' ';}cout << num[i][8] << endl;}flag = true;return;}int h = n / 9; // 行号int l = n % 9; // 列号// 如果当前位置为0,说明需要推算if (num[h][l] == 0) {// 枚举1-9的数字,判断哪个满足条件for (int i = 1; i <= 9; ++i) {num[h][l] = i;// 判断当前数字是否满足条件if (check(n)) {// 如果满足条件继续往下递归dfs(n + 1);// 如果flag为true表示整个盘面的递归结束了if (flag)return;}}// 需要回溯,恢复num[h][l]的值为0num[h][l] = 0;} else { // 当前位置不为0,往下一格递归dfs(n + 1);}
}int main() {for (int i = 0; i < 9; ++i) {for (int j = 0; j < 9; ++j) {cin >> num[i][j];}}dfs(0); // 从左上角开始递归return 0;
}
// 64 位输出请用 printf("%lld")
HJ45 名字的漂亮度
描述
给出一个字符串,该字符串仅由小写字母组成,定义这个字符串的“漂亮度”是其所有字母“漂亮度”的总和。
每个字母都有一个“漂亮度”,范围在1到26之间。没有任何两个不同字母拥有相同的“漂亮度”。字母忽略大小写。
给出多个字符串,计算每个字符串最大可能的“漂亮度”。
本题含有多组数据。
输入描述:
第一行一个整数N,接下来N行每行一个字符串
输出描述:
每个字符串可能的最大漂亮程度
代码:
#include <functional>
#include <iostream>
#include <vector>
using namespace std;int maxBeauty(const string& s) {vector<int> cnt(26, 0);for (const char& c : s)cnt[c - 'a']++;sort(cnt.begin(), cnt.end(), greater<>());int b = 26, sum = 0;for (int i = 0; i < 26; i++) {sum += cnt[i] * b;b--;}return sum;
}int main() {int n;cin >> n;string s;for (int i = 0; i < n; i++) {cin >> s;cout << maxBeauty(s) << endl;}return 0;
}
// 64 位输出请用 printf("%lld")
HJ46 截取字符串
描述
输入一个字符串和一个整数 k ,截取字符串的前k个字符并输出
输入描述:
1.输入待截取的字符串
2.输入一个正整数k,代表截取的长度
输出描述:
截取后的字符串
代码:
#include <iostream>
using namespace std;int main() {string input;cin >> input;int k;cin >> k;cout << input.substr(0, k) << endl;return 0;
}
// 64 位输出请用 printf("%lld")
HJ48 从单向链表中删除指定值的节点
描述
输入一个单向链表和一个节点的值,从单向链表中删除等于该值的节点,删除后如果链表中无节点则返回空指针。
链表的值不能重复。
输入描述:
输入一行,有以下4个部分:
1 输入链表结点个数
2 输入头结点的值
3 按照格式插入各个结点
4 输入要删除的结点的值
输出描述:
输出一行
输出删除结点后的序列,每个数后都要加空格
代码:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;int main() {int n;cin >> n;vector<int> arr;int x;cin >> x;arr.push_back(x);for (int i = 1; i < n; i++) {int num, ins;// 在 ins 的后面插入 numcin >> num >> ins;auto it = find(arr.begin(), arr.end(), ins);if (it != arr.end())arr.insert(it + 1, num);elsearr.push_back(num);}int del;cin >> del;arr.erase(find(arr.begin(), arr.end(), del));for (int& x : arr)cout << x << " ";return 0;
}
// 64 位输出请用 printf("%lld")
** HJ50 四则运算
描述
输入一个表达式(用字符串表示),求这个表达式的值。
保证字符串中的有效字符包括[‘0’-‘9’],‘+’,‘-’, ‘*’,‘/’ ,‘(’, ‘)’,‘[’, ‘]’,‘{’ ,‘}’。且表达式一定合法。
输入描述:
输入一个算术表达式
输出描述:
得到计算结果
代码:
#include <cctype>
#include <iostream>
#include <stack>
using namespace std;void compute(stack<int>& ns, stack<char>& ops) {int num2 = ns.top();ns.pop();int num1 = ns.top();ns.pop();char op = ops.top();ops.pop();int res;switch (op) {case '+':res = num1 + num2;break;case '-':res = num1 - num2;break;case '*':res = num1 * num2;break;case '/':res = num1 / num2;break;}ns.push(res);
}// 比较运算符优先级
bool priority(char m, char n) {if (m == '(') // 括号优先级最高return false;// 加减法小于乘除法else if ((m == '+' || m == '-') && (n == '*' || n == '/'))return false;return true;
}int main() {string s;cin >> s;stack<int> ns;stack<char> ops;ops.push('(');s += ')';bool flag = false;for (int i = 0; i < s.length(); i++) {// 遇到左括号if (s[i] == '(' || s[i] == '[' || s[i] == '{')ops.push('(');// 遇到右括号else if (s[i] == ')' || s[i] == ']' || s[i] == '}') {// 弹出开始计算直到遇到左括号while (ops.top() != '(')compute(ns, ops);// 弹出左括号ops.pop();}// 遇到运算符else if (flag) {// 当s[i]的优先级小于等于栈顶符号优先级时,对栈顶进行一次计算,直到不符合条件while (priority(ops.top(), s[i]))compute(ns, ops);// 需要将当前运算符加入栈中等待运算ops.push(s[i]);flag = false;}// 遇到数字else {int j = i;if (s[j] == '-' || s[j] == '+')i++;while (isdigit(s[i]))i++;ns.push(stoi(s.substr(j, i - j)));i--;// 数字结束,下一次flag为true就是运算符了flag = true;}}cout << ns.top() << endl;return 0;
}
// 64 位输出请用 printf("%lld")