华为机试真题练习汇总(51~60)
华为机试真题练习汇总(51~60)
题目来源:华为机试 - 牛客
标记 * 号的代表有难度的题目。
HJ51 输出单向链表中倒数第k个结点
描述
输入一个单向链表,输出该链表中倒数第k个结点,链表的倒数第1个结点为链表的尾指针。
要求:
(1)正序构建链表;
(2)构建后要忘记链表长度。
输入描述:
输入说明
1 输入链表结点个数
2 输入链表的值
3 输入k的值
输出描述:
输出一个整数
代码:
#include <iostream>
using namespace std;
struct ListNode {
int m_nKey;
ListNode* m_pNext;
ListNode(): m_nKey(0), m_pNext(nullptr) {};
ListNode(int x): m_nKey(x), m_pNext(nullptr) {};
};
ListNode* FindKthToTail(ListNode* head, int k) {
ListNode* fast = head;
ListNode* slow = head;
while (k--) {
if (fast)
fast = fast->m_pNext;
else
return nullptr;
}
while(fast)
{
fast = fast->m_pNext;
slow = slow->m_pNext;
}
return slow;
}
int main()
{
int n;
while (cin >> n) {
// 建立单链表
ListNode* head = new ListNode(-1);
ListNode* cur = head;
for (int i = 0; i < n; i++) {
int x;
cin >> x;
ListNode* nxt = new ListNode(x);
cur->m_pNext = nxt;
cur = cur->m_pNext;
}
int k;
cin >> k;
ListNode* p = FindKthToTail(head->m_pNext, k);
if (p)
cout << p->m_nKey << endl;
}
return 0;
}
// 64 位输出请用 printf("%lld")
HJ52 计算字符串的编辑距离
描述
Levenshtein 距离,又称编辑距离,指的是两个字符串之间,由一个转换成另一个所需的最少编辑操作次数。许可的编辑操作包括将一个字符替换成另一个字符,插入一个字符,删除一个字符。编辑距离的算法是首先由俄国科学家 Levenshtein 提出的,故又叫 Levenshtein Distance 。
例如:
字符串A: abcdefg
字符串B: abcdef
通过增加或是删掉字符 ”g” 的方式达到目的。这两种方案都需要一次操作。把这个操作所需要的次数定义为两个字符串的距离。
要求:
给定任意两个字符串,写出一个算法计算它们的编辑距离。
输入描述:
每组用例一共2行,为输入的两个字符串
输出描述:
每组用例输出一行,代表字符串的距离
代码:
#include <iostream>
#include <vector>
using namespace std;
int minDistance(string& word1, string& word2) {
// 特判
if (word1.empty())
return word2.size();
if (word2.empty())
return word1.size();
int len1 = word1.size(), len2 = word2.size();
// 状态矩阵
// dp[i,j]: word1到位置i为止,和word2到位置j为止,最少需要几步编辑
vector<vector<int>> dp(len1 + 1, vector<int>(len2 + 1, 0));
// 初始化
for (int i = 0; i <= len1; i++)
dp[i][0] = i;
for (int j = 0; j <= len2; j++)
dp[0][j] = j;
// 状态转移
for (int i = 1; i <= len1; i++)
for (int j = 1; j <= len2; j++) {
// 当第i位和第j位对应的字符相同时,无需操作
if (word1[i - 1] == word2[j - 1])
dp[i][j] = dp[i - 1][j - 1];
// 当二者对应的字符不同时,
// 修改的消耗是dp[i-1][j-1]+1
// 插入i位置/删除j位置的消耗是dp[i][j-1]+1,
// 插入j位置/删除i位置的消耗是dp[i-1][j]+1
else {
int op1 = dp[i - 1][j - 1] + 1;
int op2 = dp[i - 1][j] + 1;
int op3 = dp[i][j - 1] + 1;
dp[i][j] = min(op1, min(op2, op3));
}
}
return dp[len1][len2];
}
int main() {
string s1, s2;
cin >> s1 >> s2;
cout << minDistance(s1, s2) << endl;
return 0;
}
// 64 位输出请用 printf("%lld")
HJ53 杨辉三角的变形
描述
求杨辉三角第n行第一个偶数出现的位置。如果没有偶数,则输出-1。例如输入3,则输出2,输入4则输出3,输入2则输出-1。
输入描述:
输入一个int整数
输出描述:
输出返回的int值
代码:
#include <iostream>
using namespace std;
int main() {
// 规律:-1, -1, 2, 3, 2, 4, 2, 3, 2, 4...
int n;
cin >> n;
if (n <= 2)
cout << -1 << endl;
else {
int ans[] = {2, 3, 2, 4};
cout << ans[(n - 3) % 4] << endl;
}
return 0;
}
// 64 位输出请用 printf("%lld")
* HJ54 表达式求值
描述
给定一个字符串描述的算术表达式,计算出结果值。
输入字符串长度不超过 100 ,合法的字符包括 ”+, -, *, /, (, )” , ”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")
HJ55 挑7
描述
输出 1到n之间 的与 7 有关数字的个数。
一个数与7有关是指这个数是 7 的倍数,或者是包含 7 的数字(如 17 ,27 ,37 … 70 ,71 ,72 ,73…)
输入描述:
一个正整数 n 。( n 不大于 30000 )
输出描述:
一个整数,表示1到n之间的与7有关的数字个数。
代码:
#include <iostream>
using namespace std;
bool has7(int x) {
bool judge = false;
while (x) {
if (x % 10 == 7) {
judge = true;
break;
}
x /= 10;
}
return judge;
}
int main() {
int n;
cin >> n;
int count = 0;
for (int i = 1; i <= n; i++) {
if (i % 7 == 0 || has7(i))
count++;
}
cout << count << endl;
return 0;
}
// 64 位输出请用 printf("%lld")
HJ56 完全数计算
描述
完全数(Perfect number),又称完美数或完备数,是一些特殊的自然数。
它所有的真因子(即除了自身以外的约数)的和(即因子函数),恰好等于它本身。
例如:28,它有约数1、2、4、7、14、28,除去它本身28外,其余5个数相加,1+2+4+7+14=28。
输入描述:
输入一个数字n
输出描述:
输出不超过n的完全数的个数
代码:
#include <iostream>
#include <numeric>
#include <vector>
using namespace std;
bool isPrefect(int x) {
vector<int> v;
for (int i = 1; i < x; i++)
if (x % i == 0)
v.push_back(i);
return accumulate(v.begin(), v.end(), 0) == x;
}
int main() {
int n;
cin >> n;
int cnt = 0;
for (int x = 1; x <= n; x++)
if (isPrefect(x))
cnt++;
cout << cnt << endl;
return 0;
}
// 64 位输出请用 printf("%lld")
HJ57 高精度整数加法
描述
输入两个用字符串 str 表示的整数,求它们所表示的数之和。
输入描述:
输入两个字符串。保证字符串只含有’0’~'9’字符
输出描述:
输出求和后的结果
代码:
#include <algorithm>
#include <any>
#include <iostream>
using namespace std;
int main() {
string num1, num2;
cin >> num1 >> num2;
string ans;
int i = num1.length() - 1, j = num2.length() - 1;
int add = 0;
while (i >= 0 || j >= 0) {
int d1 = i >= 0 ? num1[i] - '0' : 0;
int d2 = j >= 0 ? num2[j] - '0' : 0;
int sum = d1 + d2 + add;
i--;
j--;
ans.push_back(sum % 10 + '0');
add = sum / 10;
}
if (add)
ans.push_back('1');
reverse(ans.begin(), ans.end());
cout << ans << endl;
return 0;
}
// 64 位输出请用 printf("%lld")
HJ58 输入n个整数,输出其中最小的k个
描述
输入n个整数,找出其中最小的k个整数并按升序输出
本题有多组输入样例
输入描述:
第一行输入两个整数n和k
第二行输入一个整数数组
输出描述:
从小到大输出最小的k个整数,用空格分开。
代码:
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
int main() {
int n, k;
while (cin >> n >> k) {
vector<int> v(n);
for (int i = 0; i < n; i++)
cin >> v[i];
sort(v.begin(), v.end());
for (int i = 0; i < k; i++)
cout << v[i] << ' ';
}
return 0;
}
// 64 位输出请用 printf("%lld")
HJ59 找出字符串中第一个只出现一次的字符
描述
找出字符串中第一个只出现一次的字符
输入描述:
输入一个非空字符串
输出描述:
输出第一个只出现一次的字符,如果不存在输出-1
代码:
#include <iostream>
#include <unordered_map>
using namespace std;
int main() {
string s;
cin >> s;
unordered_map<char, int> cnt;
for (char& c : s)
cnt[c]++;
char ch;
bool find = false;
for (char& c : s)
if (cnt[c] == 1) {
find = true;
ch = c;
break;
}
if (find)
cout << ch << endl;
else
cout << -1 << endl;
return 0;
}
// 64 位输出请用 printf("%lld")
HJ60 查找组成一个偶数最接近的两个素数
描述
任意一个偶数(大于2)都可以由2个素数组成,组成偶数的2个素数有很多种情况,本题目要求输出组成指定偶数的两个素数差值最小的素数对。
输入描述:
输入一个大于2的偶数
输出描述:
从小到大输出两个素数
代码:
#include <iostream>
using namespace std;
bool isPrime(int x) {
for (int i = 2; i * i <= x; i++)
if (x % i == 0)
return false;
return true;
}
int main() {
int n;
cin >> n;
for (int i = n / 2; i >= 1; i--)
if (isPrime(i) && isPrime(n - i)) {
cout << i << endl << n - i << endl;
break;
}
return 0;
}
// 64 位输出请用 printf("%lld")