华为机试真题练习汇总(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")
  • 20
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

UestcXiye

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

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

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

打赏作者

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

抵扣说明:

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

余额充值