【满分】【华为OD机试真题2023C&D卷 JAVA&JS】文件缓存系统

华为OD2023(C&D卷)机试题库全覆盖,刷题指南点这里

文件缓存系统

时间限制:2s 空间限制:32MB 限定语言:不限

题目描述:

请设计一个文件缓存系统,该文件缓存系统可以指定缓存的最大值(单位为字节)。
文件缓存系统有两种操作:存储文件(put)和读取文件(get)
操作命令为put fileName fileSize或者get fileName
存储文件是把文件放入文件缓存系统中;读取文件是从文件缓存系统中访问已存在的文件,如果文件不存在,则不作任何操作。
当缓存空间不足以存放新的文件时,根据规则删除文件,直到剩余空间满足新的文件大小为止,再存放新文件。
具体的删除规则为:
文件访问过后,会更新文件的最近访问时间和总的访问次数,当缓存不够时,按照第一优先顺序为访问次数从少到多,第二顺序为时间从老到新的方式来删除文件。

输入描述:

第一行为缓存最大值m(整数,取值范围为0 < m <= 52428800);

第二行为文件操作序列个数n(0 <= n <= 300000
从第三行起为文件操作序列,每个序列单独一行
文件操作定义为"op file_namefile_size"
file_name是文件名,file_size是文件大小

输出描述:

输出当前文件缓存中的文件名列表,文件名用英文逗号分隔,按字典顺序排序
如:
a,c
如果文件缓存中没有文件,则输出NONE

补充说明:

1.  如果新文件的文件名和文件缓存中已有的文件名相同,则不会放在缓存中

2.  新的文件第一次存入到文件缓存中时,文件的总访问次数不会变化,文件的最近访问时间会更新到最新时间

3.  每次文件访问后,总访问次数加1,最近访问时间更新到最新时间

4.  任何两个文件的最近访问时间不会重复

5.  文件名不会为空,均为小写字母,最大长度为10。

6.  缓存空间不足时,不能存放新文件

7.  每个文件大小都是大于0的整数

示例1

输入:

50
6
put a 10
put b 20
get a
get a
get b
put c 30

输出:

a,c

示例2

输入:

50
1
get file

输出:

NONE

代码(JAVA): 

import java.util.*;
import java.util.stream.Collectors;

public class Main{

    public static void main(String[] args) {

        Scanner in = new Scanner(System.in);

        int m = in.nextInt();
        int n = in.nextInt();
        Map<String, File> fileMap = new HashMap<>();
        //文件所占容量
        int sum = 0;
        //相当于访问时间,index 越大,访问时间越晚
        int index = 1;
        in.nextLine();
        for (int i = 0; i < n; i++) {
            String[] arr = in.nextLine().split(" ");
            if ("get".equals(arr[0])) {
                File file = fileMap.get(arr[1]);
                if (Objects.isNull(file)) {
                    continue;
                }
                //访问次数 +1
                file.times ++;
                //最新时间更新
                file.index = index ++;
            } else {
                if (fileMap.containsKey(arr[1])) {
                    //已缓存不做任何处理
                    continue;
                }
                int size = Integer.valueOf(arr[2]);
                if (sum + size > m) {
                    //不够放了需要删除
                    sum = remove( fileMap, m, sum, size);
                }
                if (sum + size <= m) {
                    sum += size;
                    fileMap.put( arr[1], new File( arr[1], size, index ++));
                }
            }
        }
        if (fileMap.isEmpty()) {
            System.out.println("NONE");
        } else {
            System.out.println(fileMap.keySet().stream().sorted().collect(Collectors.joining(",")));
        }

    }

    public static int remove(Map<String, File> fileMap, int total, int now, int size) {
        //根据访问次数和最新访问时间进行排序
        List<File> list = fileMap.values().stream()
                .sorted(Comparator.comparing(File::getTimes).thenComparing(File::getIndex))
                .collect(Collectors.toList());
        int result = now;
        for (File file : list) {
            if (result + size >= total) {
                fileMap.remove(file.fileName);
                result = result - file.size;
            } else {
                break;
            }
        }
        return result;
    }

    static class File {

        String fileName;
        int size;
        int times;
        int index;

        public File(String fileName, int size, int index) {
            this.fileName = fileName;
            this.size = size;
            this.index = index;
        }

        public int getIndex() {
            return index;
        }

        public int getTimes() {
            return times;
        }
    }
}

代码(JS):

let m = parseInt("50");
let n = parseInt("6");

class File {
    constructor(fileName, size, index) {
        this.fileName = fileName;
        this.size = size;
        this.times = 0;
        this.index = index;
    }
}

let fileMap = new Map();
let sum = 0;
let index = 1;
let test = [
    "put a 10",
    "put b 20",
    "get a",
    "get a",
    "get b",
    "put c 30"
];
for (let i = 0; i < n; i++) {

    let arr = test[i].split(' ');
    if (arr[0] === 'get') {
        let file = fileMap.get(arr[1]);
        if (!file) {
            continue;
        }
        file.times++;
        file.index = index++;
    } else {
        if (fileMap.has(arr[1])) {
            continue;
        }
        let size = parseInt(arr[2]);
        if (sum + size > m) {
            sum = remove(fileMap, m, sum, size);
        }
        if (sum + size <= m) {
            sum += size;
            fileMap.set(arr[1], new File(arr[1], size, index++));
        }
    }

}

if (fileMap.size === 0) {
    console.log('NONE');
} else {
    let keys = Array.from(fileMap.keys()).sort().join(',');
    console.log(keys);
}

function remove(fileMap, total, now, size) {
    let list = Array.from(fileMap.values()).sort((a, b) => {
        if (a.times === b.times) {
            return a.index - b.index;
        } else {
            return a.times - b.times;
        }
    });
    let result = now;
    for (let file of list) {
        if (result + size >= total) {
            fileMap.delete(file.fileName);
            result -= file.size;
        } else {
            break;
        }
    }
    return result;
}
  • 25
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值