华为OD机试 - 文件缓存系统——优先队列解法

华为OD机试 - 文件缓存系统——优先队列解法

题目描述

题目描述链接🔗

题目分析

  • 这题需要我们实现一个LFUCache的自定义数据结构,根据题意,需要分别定义一个putget方法,用于存储缓存和获取缓存。
  • 本题难点在于put方法中,如果当前缓存空间如果不够存放新加入的缓存,则需要将已有缓存根据条件进行删除,直到可以存放新加的缓存。这里的条件是两个维度,分别是访问次数(少->多)、访问时间(老->新)。
  • 我们需要一个数据结构来通过这两个条件,对加入的缓存进行排序,方便我们快速获取要删除的缓存,这里我们选择优先队列进行存储。并将访问次数和访问时间这两个属性将缓存封装为Cache的数据结构,通过这两个属性对Cache进行排序即可。

代码解析

代码已AC,细节见下面注释👇🏻

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int capacity = Integer.parseInt(sc.nextLine());
        int n = Integer.parseInt(sc.nextLine());
        LFUCache lfuCache = new LFUCache(capacity);
        //读取后续n个操作
        for (int i = 1; i <= n; i++) {
            String[] str = sc.nextLine().split(" ");
            //这里通过数组长度判断put/get操作,也可以通过第0个索引的字符串判断
            if (str.length == 3) {
                lfuCache.put(str[1], Integer.parseInt(str[2]), i);
            } else if (str.length == 2) {
                lfuCache.get(str[1], i);
            }
        }
        lfuCache.printCaches();
    }

    private static class LFUCache {
        private static int capacity;

        //缓存中剩余的空间
        private static int freeCap;

        private static final HashMap<String, Cache> name2File = new HashMap<>();

        //按访问次数从少到多,访问时间从老到新(从小到大)对缓存排序
        private static final PriorityQueue<Cache> pq = new PriorityQueue<>((a, b) ->
                a.visitCount == b.visitCount ? (a.visitTime - b.visitTime)
                        : a.visitCount - b.visitCount);

        public LFUCache(int capacity) {
            LFUCache.capacity = capacity;
            freeCap = capacity;
        }

        public void put(String fileName, int fileSize, int visitTime) {
            if (name2File.containsKey(fileName) || fileSize > capacity) {
                return;
            }
            Cache cache = new Cache(fileName, fileSize, visitTime);
            if (freeCap < cache.size) {
                //LFUCache剩余空间不够时,需要将已有缓存移除,直到满足当前新缓存cache
                while (freeCap < cache.size) {
                    if (pq.size() == 0) {
                        return;
                    }
                    //移除时需要将map和pq中的同一个对象都移除
                    Cache removed = pq.poll();
                    name2File.remove(removed.name);
                    freeCap += removed.size;
                }
            }
            //新加入时也要分别存储
            name2File.put(fileName, cache);
            pq.offer(cache);
            freeCap -= fileSize;
        }

        public void get(String fileName, int visitTime) {
            Cache cache = name2File.get(fileName);
            if (cache == null) {
                return;
            }
            //更新cache访问次数和时间
            cache.visitCount++;
            cache.visitTime = visitTime;
            //这个cache在map和优先队列中是同一个对象,修改了上面两个属性后优先队列并未重新排序
            //因此这里通过将cache重新加入队列的方式进行重新排序
            pq.remove(cache);
            pq.add(cache);
        }

        public void printCaches() {
            Collection<Cache> values = name2File.values();
            //没有缓存时,打印NONE
            if (values.size() == 0) {
                System.out.println("NONE");
            }
            StringJoiner sj = new StringJoiner(",");
            //剩余缓存字典序排序输出
            values.stream().sorted((a, b) -> a.name.compareTo(b.name))
                    .forEach(a -> sj.add(a.name));
            System.out.println(sj);
        }
    }

    private static class Cache {
        String name;
        int size;
        int visitCount;
        //访问时间,值越大访问时间越新
        int visitTime;

        public Cache(String name, int size, int visitTime) {
            this.name = name;
            this.size = size;
            this.visitCount = 0;
            this.visitTime = visitTime;
        }
    }
}

复杂度分析

时间复杂度:O(nlogn),优先队列一次put或get操作需要O(logn)的时间,n个元素共需要O(nlogn),n是操作数量。
空间复杂度:O(n),n是操作数量,主要是一个哈希表和优先队列所占空间。

相关推荐

  1. 华为OD - 文件缓存系统——优先队列解法

    2024-07-23 08:18:02       19 阅读
  2. 华为OD C++ -采样过滤

    2024-07-23 08:18:02       35 阅读
  3. 华为OD Python -采样过滤

    2024-07-23 08:18:02       32 阅读
  4. 华为ODC++】取近似值

    2024-07-23 08:18:02       29 阅读
  5. 华为ODC++】生成随机数

    2024-07-23 08:18:02       34 阅读
  6. 华为ODC++】蛇形矩阵

    2024-07-23 08:18:02       39 阅读
  7. 华为ODC++】图片整理

    2024-07-23 08:18:02       40 阅读
  8. 华为OD】处理器问题

    2024-07-23 08:18:02       26 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-23 08:18:02       52 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-23 08:18:02       54 阅读
  3. 在Django里面运行非项目文件

    2024-07-23 08:18:02       45 阅读
  4. Python语言-面向对象

    2024-07-23 08:18:02       55 阅读

热门阅读

  1. 计算机网络之数据链路层

    2024-07-23 08:18:02       15 阅读
  2. 今天是闭包,装饰器和案例

    2024-07-23 08:18:02       17 阅读
  3. 【Golang 面试基础题】每日 5 题(三)

    2024-07-23 08:18:02       16 阅读
  4. 【策略模式在项目中的实际应用】

    2024-07-23 08:18:02       16 阅读
  5. 前端设计模式面试题汇总

    2024-07-23 08:18:02       13 阅读
  6. 预训练语言模型实践笔记

    2024-07-23 08:18:02       16 阅读
  7. 坑人的macos tar 命令 (实际上是bsdtar)换用 gnu tar

    2024-07-23 08:18:02       16 阅读
  8. windows下玩转DockerDesktop--学习笔记

    2024-07-23 08:18:02       15 阅读
  9. 45、PHP 实现滑动窗口的最大值

    2024-07-23 08:18:02       15 阅读
  10. PHP框架简介

    2024-07-23 08:18:02       11 阅读
  11. Scratch语言详解

    2024-07-23 08:18:02       13 阅读
  12. GCD异步与同步任务执行顺序分析

    2024-07-23 08:18:02       14 阅读
  13. 设计模式-策略模式

    2024-07-23 08:18:02       16 阅读