华为OD机试 2024E卷题库疯狂收录中,刷题点这里
专栏导读
本专栏收录于《华为OD机试(JAVA)真题(E卷+D卷+A卷+B卷+C卷)》。
刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新,全天CSDN在线答疑。
一、题目描述
静态扫描可以快速识别源代码的缺陷,静态扫描的结果以扫描报告作为输出:
- 文件扫描的成本和文件大小相关,如果文件大小为N,则扫描成本为N个金币。
- 扫描报告的缓存成本和文件大小无关,每缓存一个报告需要M个金币。
- 扫描报告缓存后,后续再碰到该文件则不需要扫描成本,直接获取缓存结果。
给出源代码文件标识序列F和文件大小序列S,求解采用合理的缓存策略Q,最少需要的金币数。
二、输入描述
第一行为缓存一个报告金币数M,L <= M <= 100。
第二行为文件标识序列:F1,F2,F3,…,Fn。
第三行为文件大小序列:S1,S2,S3,…,Sn。
备注:
1 <= N <= 10000
1 <= Fi <= 1000
1 <= Si <= 10
三、输出描述
采用合理的缓存策略,需最少的金币数。
四、测试用例
测试用例1:
1、输入
5
1 2 2 1 3 4
1 1 1 1 1 1
2、输出
6
3、说明
文件1和文件2各出现2次,文件3和文件4各出现1次。
判断是否缓存:
文件1:M=5 vs (2-1)1=1 → 不缓存,成本 21=2
文件2:M=5 vs (2-1)1=1 → 不缓存,成本 21=2
文件3:出现1次,不缓存,成本 11=1
文件4:出现1次,不缓存,成本 11=1
总成本:2 + 2 + 1 + 1 = 6
测试用例2:
1、输入
5
2 2 2 2 2
3 3 3 3 3
2、输出
8
3、说明
文件2出现5次,大小为3。
判断是否缓存:
文件2:M=5 vs (5-1)*3=12 → 缓存,成本 3 + 5=8
总成本:8
五、解题思路
- 统计文件出现次数和大小
- 使用两个哈希表(或字典)
- fileFrequencyMap:记录每个文件ID出现的次数,fileSizeMap:记录每个文件ID对应的文件大小。
- 计算总成本
- 遍历每个唯一的文件ID,对于每个文件,比较两种策略的成本:
- 不缓存:每次扫描都需要支付文件大小的成本,总成本为 frequency * size。
- 缓存:第一次扫描支付文件大小的成本和缓存成本 M,后续不需要再次支付扫描成本,总成本为 size + M。
- 选择两种策略中成本较低的一种,累加到总成本中。
- 遍历每个唯一的文件ID,对于每个文件,比较两种策略的成本:
- 输出结果:
- 输出计算得到的最小总金币成本。
对于每个文件,若 frequency * size 小于或等于 size + M,则不缓存,支付总扫描成本;否则,选择缓存,支付 size + M。
六、Java算法源码
public class OdTest02 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// 从控制台读取缓存大小m
int M = Integer.parseInt(scanner.nextLine());
// 读取文件ID数组
Integer[] fileIds = Arrays.stream(scanner.nextLine().split(" ")).map(Integer::parseInt).toArray(Integer[]::new);
// 读取文件大小数组
Integer[] fileSizes = Arrays.stream(scanner.nextLine().split(" ")).map(Integer::parseInt).toArray(Integer[]::new);
// 输出计算结果
System.out.println(calculateTotalCost(M, fileIds, fileSizes));
}
/**
* 计算总扫描成本
* @param cacheSize 缓存大小
* @param fileIds 文件ID数组
* @param fileSizes 文件大小数组
* @return 总扫描成本
*/
public static int calculateTotalCost(int cacheSize, Integer[] fileIds, Integer[] fileSizes) {
// fileFrequencyMap 用于保存每个文件ID的出现次数
HashMap<Integer, Integer> fileFrequencyMap = new HashMap<>();
// fileSizeMap 用于保存每个文件的大小
HashMap<Integer, Integer> fileSizeMap = new HashMap<>();
// 遍历文件ID,记录每个文件的出现次数和大小
for (int i = 0; i < fileIds.length; i++) {
Integer fileId = fileIds[i];
fileFrequencyMap.put(fileId, fileFrequencyMap.getOrDefault(fileId, 0) + 1);
fileSizeMap.putIfAbsent(fileId, fileSizes[i]);
}
int totalCost = 0;
// 遍历每个文件ID,计算每个文件的最小扫描成本
for (Integer fileId : fileFrequencyMap.keySet()) {
int frequency = fileFrequencyMap.get(fileId);
int size = fileSizeMap.get(fileId);
// 选择重复扫描文件或使用缓存的最小成本
totalCost += Math.min(frequency * size, size + cacheSize);
}
return totalCost;
}
}
七、效果展示
1、输入
10
1 1 1 1 1 1 1
2 2 2 2 2 2 2
2、输出
12
3、说明
文件1出现7次,大小为2。
判断是否缓存:
M=10 vs (7-1)*2=12 → 缓存,成本 2 + 10=12
总成本:12
🏆下一篇:华为OD机试 - 简易内存池 - 逻辑分析(Java 2024 E卷 200分)
🏆本文收录于,华为OD机试(JAVA)真题(E卷+D卷+A卷+B卷+C卷)
刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新,全天CSDN在线答疑。