首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

【华为OD-E卷 -39 静态代码扫描服务 100分(python、java、c++、js、c)】

  • 25-03-07 19:21
  • 3929
  • 10231
blog.csdn.net

【华为OD-E卷 - 静态代码扫描服务 100分(python、java、c++、js、c)】

题目

静态扫描可以快速识别源代码的缺陷,静态扫描的结果以扫描报告作为输出:
1、文件扫描的成本和文件大小相关,如果文件大小为N,则扫描成本为N个金币
2、扫描报告的缓存成本和文件大小无关,每缓存一个报告需要M个金币
3、扫描报告缓存后,后继再碰到该文件则不需要扫描成本,直接获取缓存结果
给出源代码文件标识序列和文件大小序列,求解采用合理的缓存策略,最少需要的金币数

输入描述

  • 第一行为缓存一个报告金币数M,L<= M <= 100

第二行为文件标识序列:F1,F2,F3,…,Fn。

第三行为文件大小序列:S1,S2,S3,…,Sn

输出描述

  • 采用合理的缓存策略,需要的最少金币数

备注

  • 1 <= N <= 10000 1 <= Fi <= 1000 1 <= Si <= 10

用例

用例一:
输入:
5
1 2 2 1 2 3 4
1 1 1 1 1 1 1
  • 1
  • 2
  • 3
输出:
7
  • 1
用例二:
输入:
5
2 2 2 2 2 5 2 2 2
3 3 3 3 3 1 3 3 3
  • 1
  • 2
  • 3
输出:
9
  • 1

python解法

  • 解题思路:
  • 输入数据:

m: 额外的可用时间(每个任务额外的时间)。
f: 一个列表,表示每个任务的频率(任务的出现次数)。
s: 一个列表,表示每个任务的大小(任务所需时间)。
核心思路:

首先,我们需要统计每个任务频率的出现次数。
同时,我们还需要记录每个频率任务的大小(时间需求)。如果有多个任务有相同的频率,我们只需要记录一个任务的大小(第一个出现的大小)。
计算任务总时间:

对于每一个任务的频率 k,我们计算它的总时间:
如果任务出现 count[k] 次,且每个任务大小为 size[k],那么这个任务组的时间为 count[k] * size[k]。
但是,如果任务组的时间超过了 size[k] + m(即原本的大小加上额外的时间),我们会限制任务的时间为 size[k] + m。
返回结果:

最后将每个频率的任务时间加总,得到最终结果。

# 输入数据
m = int(input())  # 可用的额外时间
f = list(map(int, input().split()))  # 每个任务的频率(出现次数)
s = list(map(int, input().split()))  # 每个任务的大小(所需时间)

# 定义核心函数,计算结果
def getResult(m, f, s):
    max_val = max(f)  # 找到最大频率
    count = [0] * (max_val + 1)  # 用于存储每个频率出现的次数
    size = [0] * (max_val + 1)  # 用于存储每个频率对应的大小(所需时间)

    # 遍历任务,统计频率出现次数,并记录每个频率对应的任务大小
    for i in range(len(f)):
        count[f[i]] += 1  # 任务f[i]的频率出现次数加1
        if size[f[i]] == 0:  # 如果该频率还没有任务大小,则记录该任务的大小
            size[f[i]] = s[i]

    ans = 0  # 最终结果

    # 遍历所有频率,计算总时间
    for k in range(max_val + 1):
        if count[k] > 0:  # 如果某个频率的任务存在
            ans += min(count[k] * size[k], size[k] + m)  # 计算任务的总时间

    return ans  # 返回最终结果

# 调用函数并输出结果
print(getResult(m, f, s))

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

java解法

  • 解题思路
  • 输入数据:

m:表示额外的时间(用于限制任务大小)。
f:任务频率的数组,表示每个任务出现的次数(频率)。
s:任务大小的数组,表示每个任务的所需时间。
核心思路:

统计每个频率出现的次数(count)。
对于每个频率,存储对应的任务大小(size)。我们只需要记录第一次遇到的任务大小,因为频率相同的任务应该具有相同的大小。
计算任务的总时间:

对于每个频率 k:
计算出该频率任务的总扫描时间(scanCost = count[k] * size[k])。
计算任务的缓存成本(cacheCost = size[k] + m),即任务大小加上额外的时间。
任务的最终时间应该是 scanCost 和 cacheCost 的最小值。
返回结果:

将所有任务的最小时间加起来,得到最终的总时间

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        // 读取额外的时间 m
        int m = Integer.parseInt(sc.nextLine());

        // 读取频率数组 f 和大小数组 s
        Integer[] f = Arrays.stream(sc.nextLine().split(" ")).map(Integer::parseInt).toArray(Integer[]::new);
        Integer[] s = Arrays.stream(sc.nextLine().split(" ")).map(Integer::parseInt).toArray(Integer[]::new);

        // 调用 getResult 函数并输出结果
        System.out.println(getResult(m, f, s));
    }

    public static int getResult(int m, Integer[] f, Integer[] s) {
        // 使用 HashMap 来存储每个频率的任务出现次数
        Map<Integer, Integer> count = new HashMap<>();
        // 使用 HashMap 来存储每个频率对应的任务大小
        Map<Integer, Integer> size = new HashMap<>();

        // 遍历任务,统计每个频率出现的次数并记录任务的大小
        for (int i = 0; i < f.length; i++) {
            // 更新频率出现的次数
            count.put(f[i], count.getOrDefault(f[i], 0) + 1);
            // 只记录每个频率第一次出现的任务大小
            size.putIfAbsent(f[i], s[i]);
        }

        int totalCost = 0;  // 初始化总时间

        // 遍历所有频率
        for (Integer k : count.keySet()) {
            // 计算当前频率任务的扫描时间
            int scanCost = count.get(k) * size.get(k);
            // 计算任务的缓存成本(大小 + 额外时间 m)
            int cacheCost = size.get(k) + m;
            // 最终任务的时间为两者中的最小值
            totalCost += Math.min(scanCost, cacheCost);
        }

        return totalCost;  // 返回计算得到的总时间
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47

C++解法

  • 解题思路
  • 输入数据:

costCache:额外的费用(表示任务大小加上缓存的额外时间)。
identifiers:每个任务的标识符(频率数组),即每个任务的标识符,可能有重复,表示任务出现的次数。
sizes:每个任务的大小数组,表示每个任务所需的时间。
核心思路:

使用两个 map(哈希表):
occurrence:统计每个任务标识符(identifiers[i])出现的次数。
sizeMap:记录每个标识符对应的任务大小(sizes[i])。任务大小只记录第一次出现的值,后续相同标识符的任务不需要更新任务大小。
计算最小金币数:

对于每个任务标识符 id,计算该任务的总时间。
如果任务频率为 count(id),每个任务的大小为 sizeMap[id],那么任务组的总时间是 count(id) * sizeMap[id]。
然而,任务的实际时间应当是 min(count(id) * sizeMap[id], sizeMap[id] + costCache),即计算任务的总时间和缓存时间的最小值。
最终,将所有任务的最小时间加起来,得到最小金币数。
返回结果:

输出计算的总金币数。

#include 
#include 
#include 
#include 

using namespace std;

// 解析输入字符串为整数数组
vector<int> splitToInt(const string& input, char delim) {
    vector<int> output;
    string token;
    istringstream stream(input);
    // 按照给定的分隔符拆分字符串,并转换为整数
    while (getline(stream, token, delim)) {
        output.push_back(stoi(token));  // 将每个拆分出的字符串转换为整数并存入数组
    }
    return output;
}

// 计算所需金币
int minCoins(int costCache, const vector<int>& identifiers, const vector<int>& sizes) {
    // 使用map统计每个任务标识符出现的次数
    map<int, int> occurrence;
    // 使用map记录每个标识符对应的任务大小
    map<int, int> sizeMap;

    // 遍历所有任务标识符
    for (int i = 0; i < identifiers.size(); i++) {
        int id = identifiers[i];
        occurrence[id]++;  // 统计任务标识符出现的次数
        if (sizeMap.find(id) == sizeMap.end()) {  // 如果该标识符还没有记录大小
            sizeMap[id] = sizes[i];  // 记录该标识符对应的任务大小
        }
    }

    int totalCoins = 0;  // 总金币数

    // 遍历所有任务标识符的出现次数
    for (const auto& item : occurrence) {
        int id = item.first;  // 任务标识符
        // 计算任务的最小花费,取任务总扫描时间和缓存时间的最小值
        totalCoins += min(item.second * sizeMap[id], sizeMap[id] + costCache);
    }

    return totalCoins;  // 返回计算得到的总金币数
}

// 主函数负责调用逻辑并处理输入
int main() {
    int costCache;
    cin >> costCache;  // 读取额外的缓存时间

    string idStr, sizeStr;
    cin.ignore();  // 跳过多余的空行
    getline(cin, idStr);  // 读取任务标识符序列
    vector<int> identifiers = splitToInt(idStr, ' ');  // 将标识符拆分成整数数组

    getline(cin, sizeStr);  // 读取任务大小序列
    vector<int> sizes = splitToInt(sizeStr, ' ');  // 将大小拆分成整数数组

    // 调用minCoins函数计算最小金币数并输出结果
    cout << minCoins(costCache, identifiers, sizes) << endl;

    return 0;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66

C解法

  • 解题思路

更新中
  • 1

JS解法

  • 解题思路

  • 输入数据:

cacheSize:额外的缓存费用(可以理解为给任务额外分配的时间或空间)。
files:每个任务的标识符数组,表示任务的不同标识符(可能重复,表示任务的频率)。
scanCosts:每个任务的扫描成本数组,表示任务完成时所需的时间。
核心思路:

对于每个任务标识符,计算其总的扫描成本和缓存成本:
扫描成本是任务出现的次数 count(file) 与该任务的扫描时间 cost(file) 的乘积,即 count(file) * cost(file)。
缓存成本是任务大小 cost(file) 加上额外的时间 cacheSize,即 cost(file) + cacheSize。
对于每个任务标识符,选择这两者中的最小值作为该任务的实际成本。
最终计算所有任务的总成本。
详细步骤:

首先遍历任务标识符数组 files,记录每个标识符出现的次数(fileCount)以及该标识符对应的扫描成本(fileCost)。
然后,对于每个不同的任务标识符,计算该标识符的最小成本,最终累加得到总的最小成本。
返回结果:

输出所有任务的最小总成本

const readline = require("readline");

// 创建输入接口,用于处理标准输入
const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout,
});

// 用于存储输入的数据
const inputs = [];

// 监听每一行输入
rl.on("line", (line) => {
    // 将输入行存储到 inputs 数组
    inputs.push(line);
    
    // 当所有输入都读取完毕(总共读取 3 行输入)
    if (inputs.length === 3) {
        // 第一行:缓存大小
        const cacheSize = parseInt(inputs[0]);
        // 第二行:任务标识符数组
        const files = inputs[1].split(" ").map(Number);
        // 第三行:任务扫描成本数组
        const scanCosts = inputs[2].split(" ").map(Number);

        // 计算并输出最小成本
        console.log(calculateMinCost(cacheSize, files, scanCosts));
        
        // 清空 inputs 数组,准备下次输入
        inputs.length = 0;
    }
});

// 计算最小成本的函数
function calculateMinCost(cacheSize, files, scanCosts) {
    // 用于存储每个任务标识符出现的次数
    const fileCount = {};
    // 用于存储每个任务标识符对应的扫描成本
    const fileCost = {};

    // 遍历所有任务标识符
    files.forEach((file, index) => {
        // 更新该任务标识符出现的次数
        if (!fileCount[file]) fileCount[file] = 0;
        fileCount[file]++;
        
        // 记录该任务标识符对应的扫描成本(只记录第一次出现的任务)
        if (!fileCost[file]) {
            fileCost[file] = scanCosts[index];
        }
    });

    // 计算所有任务的最小成本,并返回总和
    return Object.keys(fileCount).reduce((total, file) => {
        const count = fileCount[file];  // 任务标识符出现的次数
        const cost = fileCost[file];    // 任务标识符的扫描成本
        
        // 对于每个任务,选择扫描成本和缓存成本的最小值
        return total + Math.min(count * cost, cost + cacheSize);
    }, 0);  // 初始总成本为 0
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62

注意:

如果发现代码有用例覆盖不到的情况,欢迎反馈!会在第一时间修正,更新。
解题不易,如对您有帮助,欢迎点赞/收藏

注:本文转载自blog.csdn.net的CodeClimb的文章"https://blog.csdn.net/CodeClimb/article/details/144834366"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top