华为笔试 华为笔试题 0514

笔试时间:2025年5月14日

往年笔试合集:

2023春招秋招笔试合集

2024春招秋招笔试合集

第一题:AI算法训练中的动态优先级经验回放

AI算力资源宝贵,在AI算法训练中,经验回放机制通过存储和重用过去的经验数据来提高算法训练效率,以节省算力资源和提升迭代速度。为了进一步优化,我们使用优先级经验回放,根据每个经验的TD误差(Temporal Difference Error)动态调整其采样优先级。请设计一个高效的数据结构和算法,支持以下操作:插入经验:将新经验加入经验池,并赋予初始优先级。提取Top K经验:取出优先级最高的K个经验(按优先级降序排列,若优先级相同则按id升序排列)。提取后,池中减少已提取的经验。若池中剩余经验数小于K,返回-1。更新优先级:根据训练后的TD误差,更新指定经验的优先级。每次更新后,之前提取的经验重新回到池中,且优先级为最新值。给定N个按时间顺序发生的操作(插入/提取/更新),请输出每次提取操作的结果。

输入描述

第一行为整数N,表示操作总数。接下来N行,每行表示一个操作:+id score:插入ID为id的经验,初始优先级为score。= id newScore:将ID为id的经验的优先级更新为newScore。-k:提取当前优先级最高的k个经验id。约束条件:

1 ≤ N ≤ 1e5

1 ≤ id ≤ 1e5(保证同一id不会被重复插入)

0 < score, newScore ≤ 1e9

1 ≤ k ≤ 10001

输出描述

对每个extract操作,按顺序输出提取的id列表(空格分隔)。若有多次extract操作的输出,则后面的extract操作在前一次输出结果之后换行输出。

若extract返回-1,输出-1。

若所有操作记录中没有extract操作,则返回nuIl。

若入参的操作总数N和实际的操作行数不匹配,则返回null

样例输入

7  

+ 1 5  

+ 2 10  

+ 3 7  

- 2  

= 3 20  

- 1  

- 1  

样例输出

2 3  

3  

2

解释:

初始池:[(1,5), (2,10), (3,7)]

提取Top2:优先级最高的为2(10)和3(7),输出2 3,池剩余[(1,5)]。

更新id=3的优先级为20后,池变为[(1,5), (2,10), (3,20)](之前提取的经验重新加入)。

提取Top1:优先级最高为3(20),输出3,池剩余[(1,5), (2,10)]。

再次提取Top1:优先级最高为2(10),输出2。

参考题解

模拟

C++:

#include <iostream>
#include <set>
#include <vector>
#include <string>
usingnamespacestd;

int main() {
    int n;
    cin >> n;
    
    set<pair<int, int>, greater<pair<int, int> > > experienceSet, allSet;

    unordered_map<int, pair<int, int> > idToPair;

    for (int i = 0; i < n; ++i) {
        string op;
        cin >> op;
        
        if (op == "+") {
            int id, score;
            cin >> id >> score;
            
            // 检查是否已存在该 id
            if (idToPair.find(id) != idToPair.end()) {
                continue; // 忽略已存在的 id
            }
            
            // 插入新元素
            auto p = make_pair(score, id);
            experienceSet.insert(p);
            allSet.insert(p);
            idToPair[id] = p;
            
        } elseif (op == "=") {
            int id, newScore;
            cin >> id >> newScore;
            
            // 检查是否存在该 id
            if (idToPair.find(id) == idToPair.end()) {
                continue; // 忽略不存在的 id
            }
            experienceSet = allSet; // 重置 set,使得 set 按 score 降序、id 升序排列
            
            // 从 set 中删除旧的 pair
            auto oldPair = idToPair[id];
            experienceSet.erase(oldPair);
            
            // 插入新的 pair
            auto newPair = make_pair(newScore, id);
            experienceSet.insert(newPair);
            idToPair[id] = newPair;
            
        } elseif (op == "-") {
            int k;
            cin >> k;
            
            // 检查是否有足够的元素
            if (experienceSet.size() < k) {
                cout << -1 << endl;
                continue;
            }
            
            vector<int> result;
            auto it = experienceSet.begin();
            for (int i = 0; i < k; ++i) {
                result.push_back(it->second); // 提取 id
                ++it;
            }
            
            for (int i = 0; i < result.size(); ++i) {
                cout << result[i] << (i == result.size() - 1 ? '\n' : ' ');
                auto oldPair = idToPair[result[i]];
                experienceSet.erase(oldPair);
            }
        }
    }
    
    return0;
}

Java:

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.util.*;

public class Main {
    static class Pair {
        int score, id;
        Pair(int score, int id) {
            this.score = score;
            this.id = id;
        }
    }

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int n = Integer.parseInt(br.readLine().trim());

        // 按 score 降序,id 升序
        Comparator<Pair> comp = (a, b) -> {
            if (a.score != b.score) return Integer.compare(b.score, a.score);
            return Integer.compare(a.id, b.id);
        };

        TreeSet<Pair> experienceSet = new TreeSet<>(comp);
        TreeSet<Pair> allSet = new TreeSet<>(comp);
        Map<Integer, Pair> idToPair = new HashMap<>();

        for (int i = 0; i < n; i++) {
            String[] parts = br.readLine().split("\\s+");
            String op = parts[0];

            if (op.equals("+")) {
                int id = Integer.parseInt(parts[1]);
                int score = Integer.parseInt(parts[2]);
                if (idToPair.containsKey(id)) continue;
                Pair p = new Pair(score, id);
                experienceSet.add(p);
                allSet.add(p);
                idToPair.put(id, p);

            } else if (op.equals("=")) {
                int id = Integer.parseInt(parts[1]);
                int newScore = Integer.parseInt(parts[2]);
                if (!idToPair.containsKey(id)) continue;
                // 重置 experienceSet
                experienceSet = new TreeSet<>(allSet);
                // 替换旧的
                Pair oldP = idToPair.get(id);
                experienceSet.remove(oldP);
                Pair newP = new Pair(newScore, id);
                experienceSet.add(newP);
                // 更新映射(注意:allSet 保持不变以供下次重置)
                idToPair.put(id, newP);

            } else if (op.equals("-")) {
                int k = Integer.parseInt(parts[1]);
                if (experienceSet.size() < k) {
                    System.out.println(-1);
                    continue;
                }
                Iterator<Pair> it = experienceSet.iterator();
                StringBuilder sb = new StringBuilder();
                for (int cnt = 0; cnt < k; cnt++) {
                    Pair p = it.next();
                    sb.append(p.id).append(cnt == k - 1 ? "\n" : " ");
                    it.remove();
                }
                System.out.print(sb);
            }
        }
    }
}

Python:

import sys
import bisect

def insert_sorted(lst, pair):
    # pair = ( -score, id )
    bisect.insort(lst, pair)

def remove_pair(lst, pair):
    # locate and remove one instance
    i = bisect.bisect_left(lst, pair)
    if i < len(lst) and lst[i] == pair:
        lst.pop(i)

def main():
    input_data = sys.stdin.read().split()
    it = iter(input_data)
    n = int(next(it))

    # 存储 ( -score, id ),这样默认升序即 score 降序、id 升序
    experience = []
    all_list = []
    id_to_pair = {}

    for _ in range(n):
        op = next(it)
        if op == "+":
            id_ = int(next(it))
            score = int(next(it))
            if id_ in id_to_pair:
                continue
            pair = (-score, id_)
            insert_sorted(experience, pair)
            insert_sorted(all_list, pair)
            id_to_pair[id_] = pair

        elif op == "=":
            id_ = int(next(it))
            new_score = int(next(it))
            if id_ not in id_to_pair:
                continue
            # 重置 experience
            experience = all_list.copy()
            old_pair = id_to_pair[id_]
            remove_pair(experience, old_pair)
            new_pair = (-new_score, id_)
            insert_sorted(experience, new_pair)
            id_to_pair[id_] = new_pair
            # all_list 不变,用于下次重置

        elif op == "-":
            k = int(next(it))
            if len(experience) < k:
                print(-1)
                continue
            res = []
            for _ in range(k):
                pair = experience.pop(0)
                res.append(str(pair[1]))
            print(" ".join(res))

if __name__ == "__main__":
    main()

第二题:游戏中的地图穿越

小明用 k*k 的二维矩阵 map 表示三维空间中的一个地图,map[i][j] 表示位置 [i][j] 的地形高度。玩家需控制角色从矩阵左上角 [0,0] 进入,从矩阵右侧任意位置(即第 k-1 列的任意行)出去。1.角色只能向右或向下移动。2.相邻两节点高度差绝对值若大于 1,角色无法移动(太高爬不上去,太低会摔死)。3.角色经过 [i][j] 时,消耗 map[i][j] 点体力值。 求最省体力值的路线所消耗的体力值总和。若无可行路径或参数不合法,返回特定结果。

输入描述

输入有多行,第1行为数组的行数k(k<=100),第2行至第k+1行为k*k矩阵,数组元素用空格分隔,,且 0 ≤ map

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

2025 春招笔试合集 文章被收录于专栏

2025打怪升级记录,大厂笔试合集 C++, Java, Python等多种语言做法集合指南

全部评论

相关推荐

点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务