华为 ai 机考 编程题解答

写在前面

这道题目好像是 2025年9月12日参加华为ai岗位的机试考试的一道题目。题目网上有原题,也有类似的解答,我这里主要是讲一讲我对这道题目的想法,以及通过 C + + C++ C++ 编写的代码。(网上的都是 P y t h o n Python Python 写的代码),本人还是习惯使用 C + + C++ C++ 编写。

题目

b站上有个视频,专门讲解了这道题目的思路:华为9月12日AI岗考试题讲解-二叉树中序遍历的第k个祖先节点|BFS建树,中序遍历,模拟

题目的大致意思是(具体详见:二叉树中序遍历的第k个祖先节点):

我的思路

我的思路就是:

  • 首先对输入的数据节点进行建树,这里就需要构建一个结构体 construct TreeNode ,然后建立二叉树,同时子节点有个 fa 指针,指向父节点,便于后续操作。
  • 接着对二叉树进行中序遍历,并将结果存入到一个 inorderResult 数组中。
  • 接着在 inorderResult 数组中找到需要找寻的节点 node 的位置,然后标记其所有的父节点的 isAncestor = 1,表示是该节点的祖先节点
  • 最后从该位置向前遍历,每找到一个 isAncestor = 1 的节点,则 k--,直到 k==0,返回该位置的节点值。要是遍历到第一个元素 k 依旧不为 0 的话,返回 -1 即可。

于是我根据上述思路,编写的代码如下:

cpp 复制代码
#include <iostream>
#include <vector>
#include <queue>
#include <sstream>
#include <string>

using namespace std;

struct TreeNode
{
    int val;
    int isAncestor = 0;
    TreeNode *left;
    TreeNode *right;
    TreeNode *fa; // 用来找寻父节点
    TreeNode(int x) : val(x), left(nullptr), right(nullptr), fa(nullptr) {}
};

// 从输入字符串构建二叉树(层次遍历输入,# 表示 null)
TreeNode *buildTree(const vector<string> &parts)
{
    if (parts.empty() || parts[0] == "#")
        return nullptr;

    TreeNode *root = new TreeNode(stoi(parts[0]));
    root->fa = nullptr;
    queue<TreeNode *> q; // 引入一个队列,方便建树
    q.push(root);
    size_t i = 1;

    while (!q.empty() && i < parts.size())
    {
        TreeNode *node = q.front();
        q.pop();

        // 左子节点
        if (i < parts.size() && parts[i] != "#")
        {
            node->left = new TreeNode(stoi(parts[i]));
            node->left->fa = node; // 标记其父节点
            q.push(node->left);
        }
        else
            node->left = nullptr; // 表示 parts[i] == "#" ,此时其左子节点为空
        i++;

        // 右子节点
        if (i < parts.size() && parts[i] != "#")
        {
            node->right = new TreeNode(stoi(parts[i]));
            node->right->fa = node;
            q.push(node->right);
        }
        else
            node->right = nullptr;
        i++;
    }
    return root;
}

// 中序遍历,将节点值存入 result
void inorder(TreeNode *root, vector<TreeNode *> &result)
{
    if (root == nullptr)
        return;
    inorder(root->left, result);
    result.push_back(root);
    inorder(root->right, result);
}

int main()
{
    string line;
    getline(cin, line); // 读取整行输入

    int node, k;
    cin >> node >> k; // 读取 node , k

    // 去除首尾空格
    // size_t start = line.find_first_not_of(" \t");
    // size_t end = line.find_last_not_of(" \t");
    // if (start == string::npos)
    // {
    //     cout << -1 << endl;
    //     return 0;
    // }
    // line = line.substr(start, end - start + 1);

    // 按空格分割字符串
    vector<string> parts;
    stringstream ss(line);
    string token;
    while (ss >> token)
        parts.push_back(token);

    // 构建树
    TreeNode *root = buildTree(parts);

    // 中序遍历
    vector<TreeNode *> inorderResult;
    inorder(root, inorderResult);

    // 找到目标节点在中序遍历中的位置
    int len = inorderResult.size();
    int temp = 0;
    for (; temp < len; temp++)
        if (inorderResult[temp]->val == node)
            break;

    // 目标节点的祖先节点的 isAncestor 为 1
    TreeNode *current = inorderResult[temp];
    while (current->fa != nullptr)
    {
        current->fa->isAncestor = 1;
        current = current->fa;
    }

    // 查询第 k 个祖先节点
    for (int i = temp - 1; i >= 0; i--)
    {
        if (inorderResult[i]->isAncestor == 1)
            k--;
        if (k == 0)
        {
            cout << inorderResult[i]->val << endl;
            // 重置 isAncestor 标记
            for (TreeNode *node : inorderResult)
                node->isAncestor = 0;
            return 0;
        }
    }
    // 重置 isAncestor 标记
    for (TreeNode *node : inorderResult)
        node->isAncestor = 0;
       
	  // 遍历完 k 都不为 0 ,输出 -1 即可。
    cout << -1 << endl;
    return 0;
}

我参加的一次

非常荣幸,我参加了2025年9月17号华为 ai 的机考,题目感觉出的不是很难,都是我复习到的,于是考试结果也还不错。

详细题目参见:CodeFun 2000

选择题就不做说明了,主要讲解一下编程题吧:

题目一(300分):大模型分词

题目详见:大模型分词

刚好我力扣刷到了 hot100 的动态规划专题,因此一看这道题目就是使用动态规划进行求解,只是需要对输入进行预处理即可,于是可以选择使用 C++ 中的 unordered_map 进行映射存储。

cpp 复制代码
// we have defined the necessary header files here for this problem.
// If additional header files are needed in your program, please import here.

#include <iostream>
#include <vector>
#include <string>
#include <unordered_map>
#include <climits>
// #include<bits/stdc++.h>

using namespace std;

int maxScore(const string &text, const unordered_map<string, int> &confidence, const unordered_map<string, int> &transfer)
{

    int n = text.length();
    vector<int> dp(n + 1, INT_MIN);
    dp[0] = 0;

    // 每个位置记录一下最优的前驱
    vector<int> prev(n + 1, -1);

    for (int i = 1; i <= n; i++)
    {
        for (int j = 0; j < i; j++)
        {
            string word = text.substr(j, i - j);
            if (confidence.find(word) != confidence.end())
            {
                int word_score = confidence.at(word);
                int transition_score = 0;

                // 不是第一个词的话,检查转移分数?
                if (j > 0 && prev[j] != -1)
                {
                    string prev_word = text.substr(prev[j], j - prev[j]);
                    string transition_key = prev_word + " " + word;
                    if (transfer.find(transition_key) != transfer.end())
                    {
                        transition_score = transfer.at(transition_key);
                    }
                }

                int total_score = dp[j] + word_score + transition_score;
                if (total_score > dp[i])
                {
                    dp[i] = total_score;
                    prev[i] = j; // 更新前驱位置
                }
            }
        }
    }
    return dp[n] == INT_MIN ? 0 : dp[n];
}

int main()
{
    // please define the C++ input here. For example: int a,b; cin>>a>>b;;
    // please finish the function body here.
    // please define the C++ output here. For example:cout<<____<<endl;

    // 读入英文单词
    string text;

    // 读入 n 和 m
    int n, m;
    cin >> text;
    cin >> n;

    unordered_map<string, int> confidence;
    // 已标注词元和置信度分数P,使用哈希进行存储
    for (int i = 0; i < n; i++)
    {
        string word;
        int score;
        cin >> word >> score;
        confidence[word] = score;
    }

    cin >> m;

    // 转移分数数据:起始词、下一个词、转移分数加分X、空格分隔
    unordered_map<string, int> transfer;
    for (int i = 0; i < m; i++)
    {
        string prevWord, nextWord;
        int score;
        cin >> prevWord >> nextWord >> score;
        transfer[prevWord + " " + nextWord] = score;
    }

    int result = maxScore(text, confidence, transfer);
    cout << result << endl;
    return 0;
}

但是这段代码在华为的评判系统的只过了 90% 的测试用例,还有 10% 没有通过,因此不知道主要问题在哪里,读者若有发现,麻烦详细解答一下,笔者在此不胜感激。

题目二(150分):大模型Attention模块开发

题目详见:大模型Attention模块开发

感觉要是知道点 T r a n s f o r m e r Transformer Transformer 的都应该知道这个 A t t e n t i o n Attention Attention 模块,因此这道题目还是比较好写的:

python 复制代码
# If you need to import additional packages or classes, please import here.
import numpy as np


def attention_module(n, m, h):
    # 构建全 1 的矩阵
    X = np.ones((n, m))

    # 构建上三角矩阵
    W1 = np.triu(np.ones((m, h)))
    W2 = np.triu(np.ones((m, h)))
    W3 = np.triu(np.ones((m, h)))

    # 计算 Q K V
    Q = np.dot(X, W1)
    K = np.dot(X, W2)
    V = np.dot(X, W3)

    # 计算
    QK_T = np.dot(Q, K.T)/np.sqrt(h)

    # 计算 softmax(QK_T)
    M = np.exp(QK_T)
    softmax_QK_T = M / np.sum(M, axis=1, keepdims=True)

    Y = np.dot(softmax_QK_T, V)

    return int(np.round(np.sum(Y)))


def func():

    # please define the python3 input here. For example: a,b = map(int, input().strip().split())
    # please finish the function body here.
    # please define the python3 output here. For example: print().

    # 读入输入
    n, m, h = map(int, input().strip().split())

    print(attention_module(n, m, h))


if __name__ == "__main__":
    func()
相关推荐
一灯架构15 分钟前
90%的人答错!一文带你彻底搞懂ArrayList
java·后端
SoraLuna1 小时前
「鸿蒙智能体实战记录 11」年俗文化展示卡片开发与多段内容结构化呈现实现
华为·harmonyos
网教盟人才服务平台1 小时前
“方班预备班盾立方人才培养计划”正式启动!
大数据·人工智能
Y4090011 小时前
【多线程】线程安全(1)
java·开发语言·jvm
芯智工坊1 小时前
第15章 Mosquitto生产环境部署实践
人工智能·mqtt·开源
菜菜艾1 小时前
基于llama.cpp部署私有大模型
linux·运维·服务器·人工智能·ai·云计算·ai编程
TDengine (老段)1 小时前
TDengine IDMP 可视化 —— 分享
大数据·数据库·人工智能·时序数据库·tdengine·涛思数据·时序数据
小真zzz2 小时前
搜极星:第三方多平台中立GEO洞察专家全面解析
人工智能·搜索引擎·seo·geo·中立·第三方平台
布局呆星2 小时前
SpringBoot 基础入门
java·spring boot·spring
风吹迎面入袖凉2 小时前
【Redis】Redisson的可重入锁原理
java·redis