华为机试真题练习汇总(21~30)

华为机试真题练习汇总(21~30)

题目来源:华为机试 - 牛客

标记 * 号的代表有难度的题目。

HJ21 简单密码

描述
现在有一种密码变换算法。
九键手机键盘上的数字与字母的对应: 1–1, abc–2, def–3, ghi–4, jkl–5, mno–6, pqrs–7, tuv–8 wxyz–9, 0–0,把密码中出现的小写字母都变成九键键盘对应的数字,如:a 变成 2,x 变成 9.
而密码中出现的大写字母则变成小写之后往后移一位,如:X ,先变成小写,再往后移一位,变成了 y ,例外:Z 往后移是 a 。
数字和其它的符号都不做变换。

输入描述:
输入一组密码,长度不超过100个字符。

输出描述:
输出密码变换后的字符串

代码:

#include <iostream>
using namespace std;

string pwd_change(string& s) {
    for (char& ch : s) {
        if (islower(ch)) {
            switch (ch) {
                case 'a':
                case 'b':
                case 'c':
                    ch = '2';
                    break;
                case 'd':
                case 'e':
                case 'f':
                    ch = '3';
                    break;
                case 'g':
                case 'h':
                case 'i':
                    ch = '4';
                    break;
                case 'j':
                case 'k':
                case 'l':
                    ch = '5';
                    break;
                case 'm':
                case 'n':
                case 'o':
                    ch = '6';
                    break;
                case 'p':
                case 'q':
                case 'r':
                case 's':
                    ch = '7';
                    break;
                case 't':
                case 'u':
                case 'v':
                    ch = '8';
                    break;
                case 'w':
                case 'x':
                case 'y':
                case 'z':
                    ch = '9';
                    break;
            }
        } else if (isupper(ch)) {
            ch = (ch - 'A' + 1) % 26 + 'a';
        }
    }
    return s;
}

int main() 
{
    string pwd;
    cin >> pwd;
    cout << pwd_change(pwd) << endl;
    return 0;
}
// 64 位输出请用 printf("%lld")

HJ22 汽水瓶

描述
某商店规定:三个空汽水瓶可以换一瓶汽水,允许向老板借空汽水瓶(但是必须要归还)。
小张手上有n个空汽水瓶,她想知道自己最多可以喝到多少瓶汽水。

注意:本题存在多组输入。输入的 0 表示输入结束,并不用输出结果。

输入描述:
输入文件最多包含 10 组测试数据,每个数据占一行,仅包含一个正整数 n( 1<=n<=100 ),表示小张手上的空汽水瓶数。n=0 表示输入结束,你的程序不应当处理这一行。

输出描述:
对于每组测试数据,输出一行,表示最多可以喝的汽水瓶数。如果一瓶也喝不到,输出0。

代码:

#include <iostream>
using namespace std;

int main() {
    int n;
    while (cin >> n && n) {
        int drink = 0;
        while (n >= 3) {
            drink += n / 3;
            n = n % 3 + n / 3;
        }
        if (n == 2)
            drink++;
        cout << drink << endl;
    }
    return 0;
}
// 64 位输出请用 printf("%lld")

HJ23 删除字符串中出现次数最少的字符

描述
实现删除字符串中出现次数最少的字符,若出现次数最少的字符有多个,则把出现次数最少的字符都删除。输出删除这些单词后的字符串,字符串中其它字符保持原来的顺序。

输入描述:
字符串只包含小写英文字母, 不考虑非法输入,输入的字符串长度小于等于20个字节。

输出描述:
删除字符串中出现次数最少的字符后的字符串。

代码:

#include <climits>
#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]++;

    int min_cnt = INT_MAX;
    for (auto &[ch, count] : cnt)
        min_cnt = min(min_cnt, count);

    string ans;
    for (char& c : s)
        if (cnt[c] != min_cnt)
            ans += c;

    cout << ans << endl;
    return 0;
}
// 64 位输出请用 printf("%lld")

* HJ24 合唱队

代码:

#include <iostream>
#include <vector>
using namespace std;

int main() {
    int n ;
    cin >> n;
    vector<int> heights;
    for (int i = 0; i < n; i++) {
        int h;
        cin >> h;
        heights.push_back(h);
    }

    // 最长递增子序列
    vector<int> dp1(n, 0);
    for (int i = 0; i < n; i++) {
        dp1[i] = 1;
        for (int j = 0; j < i; j++)
            if (heights[i] > heights[j])
                dp1[i] = max(dp1[i], dp1[j] + 1);
    }
    // 最长递减子序列
    vector<int> dp2(n, 0);
    for (int i = n - 1; i >= 0; i--) {
        dp2[i] = 1;
        for (int j = n - 1; j > i; j--)
            if (heights[i] > heights[j])
                dp2[i] = max(dp2[i], dp2[j] + 1);
    }

    int maxlen = 0;
    for (int i = 0; i < n; i++) {
        int len = dp1[i] + dp2[i] - 1;
        maxlen = max(maxlen, len);
    }
    cout << n - maxlen << endl;

    return 0;
}
// 64 位输出请用 printf("%lld")

* HJ25 数据分类处理

描述
信息社会,有海量的数据需要分析处理,比如公安局分析身份证号码、 QQ 用户、手机号码、银行帐号等信息及活动记录。

采集输入大数据和分类规则,通过大数据分类处理程序,将大数据分类输出。

输入描述:
一组输入整数序列I和一组规则整数序列R,I和R序列的第一个整数为序列的个数(个数不包含第一个整数);整数范围为0~(231)-1,序列个数不限

输出描述:
从R依次中取出R,对I进行处理,找到满足条件的I:

I整数对应的数字需要连续包含R对应的数字。比如R为23,I为231,那么I包含了R,条件满足 。

按R从小到大的顺序:

(1)先输出R

(2)再输出满足条件的I的个数;

(3)然后输出满足条件的I在I序列中的位置索引(从0开始);

(4)最后再输出I。

附加条件:

(1)R需要从小到大排序。相同的R只需要输出索引小的以及满足条件的I,索引大的需要过滤掉

(2)如果没有满足条件的I,对应的R不用输出

(3)最后需要在输出序列的第一个整数位置记录后续整数序列的个数(不包含“个数”本身)

代码:

#include <algorithm>
#include <iostream>
#include <memory>
#include <vector>
using namespace std;

int main() {
    int n, m, num;
    vector<int> I, R;
    cin >> n;
    for (int i = 0; i < n; i++) {
        cin >> num;
        I.push_back(num);
    }
    cin >> m;
    for (int i = 0; i < m; i++) {
        cin >> num;
        R.push_back(num);
    }

    sort(R.begin(), R.end());

    vector<int> res;
    for (int i = 0; i < m; i++) {
        if (i && R[i] == R[i - 1])
            continue;
        // 满足条件的I的个数
        int count = 0;
        // 满足条件的I在I序列中的位置索引
        vector<int> index;
        for (int j = 0; j < n; j++)
            if (to_string(I[j]).find(to_string(R[i])) != string::npos) {
                count++;
                index.push_back(j);
            }
        if (count) {
            res.push_back(R[i]);
            res.push_back(count);
            for (int& idx : index) {
                res.push_back(idx);
                res.push_back(I[idx]);
            }
        }
    }

    // 先输出后续整数序列的个数
    cout << res.size();
    for (int& x : res)
        cout << " " << x;
    cout << endl;
    return 0;
}
// 64 位输出请用 printf("%lld")

* HJ26 字符串排序

描述
编写一个程序,将输入字符串中的字符按如下规则排序。

规则 1 :英文字母从 A 到 Z 排列,不区分大小写。

如,输入: Type 输出: epTy

规则 2 :同一个英文字母的大小写同时存在时,按照输入顺序排列。

如,输入: BabA 输出: aABb

规则 3 :非英文字母的其它字符保持原来的位置。

如,输入: By?e 输出: Be?y

输入描述:
输入字符串

输出描述:
输出字符串

代码:

#include <cctype>
#include <iostream>
#include <vector>
using namespace std;

int main() {
    string s;
    getline(cin, s);
    vector<char> alpha;
    for (int i = 0; i < 26; i++)
        for (char& c : s)
            if (c - 'a' == i || c - 'A' == i)
                alpha.push_back(c);
    int idx = 0;
    for (char& c : s)
        if (isalpha(c)) {
            c = alpha[idx];
            idx++;
        }
    cout << s << endl;
    return 0;
}
// 64 位输出请用 printf("%lld")

HJ27 查找兄弟单词

描述
定义一个单词的“兄弟单词”为:交换该单词字母顺序(注:可以交换任意次),而不添加、删除、修改原有的字母就能生成的单词。
兄弟单词要求和原来的单词不同。例如: ab 和 ba 是兄弟单词。 ab 和 ab 则不是兄弟单词。
现在给定你 n 个单词,另外再给你一个单词 x ,让你寻找 x 的兄弟单词里,按字典序排列后的第 k 个单词是什么?
注意:字典中可能有重复单词。

输入描述:
输入只有一行。 先输入字典中单词的个数n,再输入n个单词作为字典单词。 然后输入一个单词x 最后后输入一个整数k

输出描述:
第一行输出查找到x的兄弟单词的个数m 第二行输出查找到的按照字典顺序排序后的第k个兄弟单词,没有符合第k个的话则不用输出。

代码:

#include <algorithm>
#include <iostream>
#include <set>
#include <vector>
using namespace std;

bool isBrother(string s1, string s2) {
    if (s1.length() != s2.length())
        return false;
    if (s1 == s2)
        return false;
    sort(s1.begin(), s1.end());
    sort(s2.begin(), s2.end());
    return s1 == s2;
}

int main() {
    int n;
    cin >> n;
    vector<string> strDict;
    string word;
    for (int i = 0; i < n; i++) {
        cin >> word;
        strDict.push_back(word);
    }
    string x;
    cin >> x;
    int k;
    cin >> k;

    vector<string> brothers;
    for (string& s : strDict)
        if (isBrother(s, x))
            brothers.push_back(s);

    cout << brothers.size() << endl;
    if (brothers.size() >= k) {
        sort(brothers.begin(), brothers.end());
        cout << brothers[k - 1] << endl;
    }
    return 0;
}
// 64 位输出请用 printf("%lld")

** HJ28 素数伴侣

描述

若两个正整数的和为素数,则这两个正整数称之为“素数伴侣”,如2和5、6和13,它们能应用于通信加密。现在密码学会请你设计一个程序,从已有的 N ( N 为偶数)个正整数中挑选出若干对组成“素数伴侣”,挑选方案多种多样,例如有4个正整数:2,5,6,13,如果将5和6分为一组中只能得到一组“素数伴侣”,而将2和5、6和13编组将得到两组“素数伴侣”,能组成“素数伴侣”最多的方案称为“最佳方案”,当然密码学会希望你寻找出“最佳方案”。

输入:

有一个正偶数 n ,表示待挑选的自然数的个数。后面给出 n 个具体的数字。

输出:

输出一个整数 K ,表示你求得的“最佳方案”组成“素数伴侣”的对数。

代码:

#include <iostream>
#include <vector>
using namespace std;

bool isprime(int num) {
    for (int i = 2; i * i <= num; i++) {
        if (num % i == 0)
            return false;
    }
    return true;
}

bool find(int num, vector<int>& evens, vector<bool>& used, vector<int>& match) {
    // 遍历每个偶数与奇数比较
    for (int i = 0; i < evens.size(); i++) {
        if (isprime(num + evens[i]) && !used[i]) {
            used[i] = true;
            if (match[i] == 0 || find(match[i], evens, used, match)) {
                // 如果第i个偶数还未配对,或者跟它配对的奇数还有别的选择
                match[i] = num; // 则配对该数
                return true;
            }
        }
    }
    return false;
}

int main() {
    int n;
    cin >> n;
    vector<int> nums(n);
    vector<int> odd; // 奇数
    vector<int> even; // 偶数
    for (int i = 0; i < n; i++) {
        cin >> nums[i];
        if (nums[i] % 2)
            odd.push_back(nums[i]);
        else
            even.push_back(nums[i]);
    }

    // 特判
    if (odd.empty() || even.empty()) {
        cout << 0 << endl;
        return 0;
    }

    int count = 0;
    vector<int> match(even.size(), 0); // 统计每个偶数的配对是哪个奇数
    // 遍历每个奇数
    for (int i = 0; i < odd.size(); i++) {
        vector<bool> used(even.size(), false); // 每一轮偶数都没用过
        // 能否找到配对的偶数,且要最优
        if (find(odd[i], even, used, match))
            count++;
    }
    cout << count << endl;

    return 0;
}
// 64 位输出请用 printf("%lld")

HJ29 字符串加解密

描述
对输入的字符串进行加解密,并输出。

加密方法为:

当内容是英文字母时则用该英文字母的后一个字母替换,同时字母变换大小写,如字母a时则替换为B;字母Z时则替换为a;

当内容是数字时则把该数字加1,如0替换1,1替换2,9替换0;

其他字符不做变化。

解密方法为加密的逆过程。

输入描述:
第一行输入一串要加密的密码
第二行输入一串加过密的密码

输出描述:
第一行输出加密后的字符
第二行输出解密后的字符

代码:

#include <cctype>
#include <iostream>
using namespace std;

string encrypt(string& s) {
    for (char& c : s) {
        if (isalpha(c)) {
            if (islower(c))
                c = (c - 'a' + 1) % 26 + 'A';
            else
                c = (c - 'A' + 1) % 26 + 'a';
        } else if (isdigit(c))
            c = (c - '0' + 1) % 10 + '0';
    }
    return s;
}

string decrypt(string& s) {
    for (char& c : s) {
        if (isalpha(c)) {
            if (islower(c))
                c = (c - 'a' + 25) % 26 + 'A';
            else
                c = (c - 'A' + 25) % 26 + 'a';
        } else if (isdigit(c))
            c = (c - '0' + 9) % 10 + '0';
    }
    return s;
}

int main() {
    string s1;
    cin >> s1;
    cout << encrypt(s1) << endl;

    string s2;
    cin >> s2;
    cout << decrypt(s2) << endl;

    return 0;
}
// 64 位输出请用 printf("%lld")

HJ30 字符串合并处理

描述
按照指定规则对输入的字符串进行处理。

详细描述:

第一步:将输入的两个字符串str1和str2进行前后合并。如给定字符串 “dec” 和字符串 “fab” , 合并后生成的字符串为 “decfab”

第二步:对合并后的字符串进行排序,要求为:下标为奇数的字符和下标为偶数的字符分别从小到大排序。这里的下标的意思是字符在字符串中的位置。注意排序后在新串中仍需要保持原来的奇偶性。例如刚刚得到的字符串“decfab”,分别对下标为偶数的字符’d’、‘c’、‘a’和下标为奇数的字符’e’、‘f’、'b’进行排序(生成 ‘a’、‘c’、‘d’ 和 ‘b’ 、‘e’ 、‘f’),再依次分别放回原串中的偶数位和奇数位,新字符串变为“abcedf”

第三步:对排序后的字符串中的’0’‘9’、‘A’‘F’和’a’~'f’字符,需要进行转换操作。
转换规则如下:
对以上需要进行转换的字符所代表的十六进制用二进制表示并倒序,然后再转换成对应的十六进制大写字符(注:字符 a~f 的十六进制对应十进制的10~15,大写同理)。
如字符 ‘4’,其二进制为 0100 ,则翻转后为 0010 ,也就是 2 。转换后的字符为 ‘2’。
如字符 ‘7’,其二进制为 0111 ,则翻转后为 1110 ,对应的十进制是14,转换为十六进制的大写字母为 ‘E’。
如字符 ‘C’,代表的十进制是 12 ,其二进制为 1100 ,则翻转后为 0011,也就是3。转换后的字符是 ‘3’。
根据这个转换规则,由第二步生成的字符串 “abcedf” 转换后会生成字符串 “5D37BF”。

输入描述:
样例输入两个字符串,用空格隔开。

输出描述:
输出转化后的结果。

代码 1:

#include <algorithm>
#include <cctype>
#include <iostream>
#include <vector>
using namespace std;

int main() {
    string str1, str2;
    cin >> str1 >> str2;

    // 第一步:将输入的两个字符串str1和str2进行前后合并
    string out = str1 + str2;
    // 第二步:对合并后的字符串进行排序,
    // 要求为:下标为奇数的字符和下标为偶数的字符分别从小到大排序
    vector<char> odd, even;
    for (int i = 0; i < out.length(); i++) {
        if (i % 2)
            odd.push_back(out[i]);
        else
            even.push_back(out[i]);
    }
    sort(odd.begin(), odd.end());
    sort(even.begin(), even.end());
    int odd_idx = 0, even_idx = 0;
    for (int i = 0; i < out.length(); i++) {
        if (i % 2)
            out[i] = odd[odd_idx++];
        else
            out[i] = even[even_idx++];
    }
    // 第三步:对排序后的字符串中的'0'~'9'、'A'~'F'和'a'~'f'字符,需要进行转换操作
    const string trans = "084C2A6E195D3B7F";
    for (char& c : out) {
        if (isdigit(c))
            c = trans[c - '0'];
        else if (c >= 'A' && c <= 'F')
            c = trans[c - 'A' + 10];
        else if (c >= 'a' && c <= 'f')
            c = trans[c - 'a' + 10];
    }
    cout << out << endl;
    return 0;
}
// 64 位输出请用 printf("%lld")

代码 2:

#include <algorithm>
#include <cctype>
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;

int reverseDec(int& num) {
    vector<int> numBin;
    while (num > 1) {
        numBin.push_back(num % 2);
        num /= 2;
    }
    numBin.push_back(num);
    while (numBin.size() < 4) {
        numBin.push_back(0);
    }
    int retVal = 0;
    for (int i = 0; i < numBin.size(); i++) {
        retVal += numBin[numBin.size() - 1 - i] * pow(2, i);
    }
    return retVal;
}

void transform(char& c) {
    int numDec;
    if (isdigit(c)) {
        numDec = c - '0';
    } else if (c >= 'A' && c <= 'F') {
        numDec = 10 + c - 'A';
    } else if (c >= 'a' && c <= 'f') {
        numDec = 10 + c - 'a';
    }
    numDec = reverseDec(numDec);
    if (numDec <= 9) {
        c = '0' + numDec;
    } else {
        c = numDec - 10 + 'A';
    }
}

int main() {
    string str1, str2;
    cin >> str1 >> str2;

    // 第一步:将输入的两个字符串str1和str2进行前后合并
    string out = str1 + str2;
    // 第二步:对合并后的字符串进行排序,
    // 要求为:下标为奇数的字符和下标为偶数的字符分别从小到大排序
    vector<char> odd, even;
    for (int i = 0; i < out.length(); i++) {
        if (i % 2)
            odd.push_back(out[i]);
        else
            even.push_back(out[i]);
    }
    sort(odd.begin(), odd.end());
    sort(even.begin(), even.end());
    int odd_idx = 0, even_idx = 0;
    for (int i = 0; i < out.length(); i++) {
        if (i % 2)
            out[i] = odd[odd_idx++];
        else
            out[i] = even[even_idx++];
    }
    // 第三步:对排序后的字符串中的'0'~'9'、'A'~'F'和'a'~'f'字符,需要进行转换操作
    const string trans = "084C2A6E195D3B7F";
    for (char& c : out) {
        if (isdigit(c) || c >= 'A' && c <= 'F' || c >= 'a' && c <= 'f')
            transform(c);
    }
    cout << out << endl;
    return 0;
}
// 64 位输出请用 printf("%lld")
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

UestcXiye

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值