华为OD机试 2024E卷题库疯狂收录中,刷题点这里
专栏导读
本专栏收录于《华为OD机试真题(Python/JS/C/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。
六、Python算法源码
# 导入所需模块
import sys
def calculate_total_cost(M, file_ids, file_sizes):
"""
计算总扫描成本
:param M: 缓存一个报告的金币数
:param file_ids: 文件ID列表
:param file_sizes: 文件大小列表
:return: 最小总金币数
"""
# 使用字典统计每个文件ID的出现次数
file_frequency_map = {}
# 使用字典记录每个文件ID对应的文件大小
file_size_map = {}
# 遍历所有文件,统计频率和记录大小
for file_id, size in zip(file_ids, file_sizes):
if file_id in file_frequency_map:
file_frequency_map[file_id] += 1
else:
file_frequency_map[file_id] = 1
file_size_map[file_id] = size
total_cost = 0
# 遍历每个唯一的文件ID,计算最小成本
for file_id in file_frequency_map:
frequency = file_frequency_map[file_id]
size = file_size_map[file_id]
# 不缓存的成本
cost_without_cache = frequency * size
# 缓存的成本
cost_with_cache = size + M
# 选择较小的成本
total_cost += min(cost_without_cache, cost_with_cache)
return total_cost
def main():
# 读取标准输入的所有行
lines = sys.stdin.read().splitlines()
# 去除可能的空行
lines = [line.strip() for line in lines if line.strip()]
# 读取缓存成本M
M = int(lines[0])
# 读取文件ID列表
file_ids = list(map(int, lines[1].split()))
# 读取文件大小列表
file_sizes = list(map(int, lines[2].split()))
# 计算总成本
total_cost = calculate_total_cost(M, file_ids, file_sizes)
# 输出结果
print(total_cost)
if __name__ == "__main__":
main()
七、JavaScript算法源码
// 导入所需模块
const readline = require('readline');
// 创建接口以读取标准输入
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
let inputLines = [];
rl.on('line', (line) => {
inputLines.push(line.trim());
// 当已经读取了三行输入时,开始处理
if (inputLines.length === 3) {
rl.close();
}
});
rl.on('close', () => {
// 读取缓存成本M
const M = parseInt(inputLines[0]);
// 读取文件ID列表
const fileIds = inputLines[1].split(' ').map(Number);
// 读取文件大小列表
const fileSizes = inputLines[2].split(' ').map(Number);
// 计算总成本
const totalCost = calculateTotalCost(M, fileIds, fileSizes);
// 输出结果
console.log(totalCost);
});
/**
* 计算总扫描成本
* @param {number} M 缓存一个报告的金币数
* @param {number[]} fileIds 文件ID数组
* @param {number[]} fileSizes 文件大小数组
* @returns {number} 最小总金币数
*/
function calculateTotalCost(M, fileIds, fileSizes) {
// 使用对象统计每个文件ID的出现次数
const fileFrequencyMap = {};
// 使用对象记录每个文件ID对应的文件大小
const fileSizeMap = {};
// 遍历所有文件,统计频率和记录大小
for (let i = 0; i < fileIds.length; i++) {
const fileId = fileIds[i];
const size = fileSizes[i];
if (fileFrequencyMap.hasOwnProperty(fileId)) {
fileFrequencyMap[fileId] += 1;
} else {
fileFrequencyMap[fileId] = 1;
fileSizeMap[fileId] = size;
}
}
let totalCost = 0;
// 遍历每个唯一的文件ID,计算最小成本
for (const fileId in fileFrequencyMap) {
const frequency = fileFrequencyMap[fileId];
const size = fileSizeMap[fileId];
const costWithoutCache = frequency * size;
const costWithCache = size + M;
totalCost += Math.min(costWithoutCache, costWithCache);
}
return totalCost;
}
八、C算法源码
#include <stdio.h>
#include <stdlib.h>
// 定义最大文件ID范围
#define MAX_FILE_ID 1001
int main() {
int M;
// 读取缓存成本M
scanf("%d", &M);
// 定义数组存储文件ID和文件大小
int fileIds[10000];
int fileSizes[10000];
int count = 0;
// 读取文件ID,直到换行或文件大小输入开始
while (scanf("%d", &fileIds[count]) != EOF) {
count++;
// 假设文件大小与文件ID数量相同
if (count >= 10000) break;
}
// 重新定位输入流到读取文件大小
// 假设输入格式正确,文件大小紧跟文件ID之后
// 重新读取文件大小
for (int i = 0; i < count; i++) {
scanf("%d", &fileSizes[i]);
}
// 使用数组统计文件频率,文件大小
int fileFrequencyMap[MAX_FILE_ID] = {0};
int fileSizeMap[MAX_FILE_ID] = {0};
for (int i = 0; i < count; i++) {
int fileId = fileIds[i];
int size = fileSizes[i];
fileFrequencyMap[fileId]++;
if (fileFrequencyMap[fileId] == 1) {
fileSizeMap[fileId] = size;
}
}
long long totalCost = 0;
// 遍历所有可能的文件ID,计算成本
for (int fileId = 0; fileId < MAX_FILE_ID; fileId++) {
if (fileFrequencyMap[fileId] > 0) {
int frequency = fileFrequencyMap[fileId];
int size = fileSizeMap[fileId];
long long costWithoutCache = (long long)frequency * size;
long long costWithCache = (long long)size + M;
// 选择较小的成本
if (costWithoutCache <= costWithCache) {
totalCost += costWithoutCache;
} else {
totalCost += costWithCache;
}
}
}
// 输出结果
printf("%lld\n", totalCost);
return 0;
}
九、C++算法源码
#include <bits/stdc++.h>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
int M;
// 读取缓存成本M
cin >> M;
// 读取文件ID序列
vector<int> fileIds;
string line;
// 读取文件ID
while(cin.peek() != '\n' && !cin.eof()){
int id;
cin >> id;
fileIds.push_back(id);
}
// 读取换行符
getline(cin, line);
// 读取文件大小序列
vector<int> fileSizes;
while(cin >> ws && !cin.eof()){
int size;
cin >> size;
fileSizes.push_back(size);
}
// 使用unordered_map统计频率和记录大小
unordered_map<int, int> fileFrequencyMap;
unordered_map<int, int> fileSizeMap;
for(int i=0; i<fileIds.size(); i++){
int fileId = fileIds[i];
int size = fileSizes[i];
fileFrequencyMap[fileId]++;
if(fileFrequencyMap[fileId] == 1){
fileSizeMap[fileId] = size;
}
}
long long totalCost = 0;
// 遍历每个文件,计算最小成本
for(auto &entry: fileFrequencyMap){
int fileId = entry.first;
int frequency = entry.second;
int size = fileSizeMap[fileId];
long long costWithoutCache = (long long)frequency * size;
long long costWithCache = (long long)size + M;
totalCost += min(costWithoutCache, costWithCache);
}
// 输出结果
cout << totalCost << "\n";
return 0;
}
🏆下一篇:华为OD机试真题 - 简易内存池(Python/JS/C/C++ 2024 E卷 200分)
🏆本文收录于,华为OD机试真题(Python/JS/C/C++)
刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新,全天CSDN在线答疑。