牛客题霸设计LRU缓存结构

tech2022-08-08  141

解析

使用2个Map,一个模拟缓存cache,一个用于记录cache中每条数据的最近访问情况。使用变量time衡量记录访问情况,每次访问/插入,time都加一,插入数据或者访问数据,则更新其最近访问情况为time,在最近访问情况中,time值最小的数据为最近未被访问的数据,每次覆盖最近未被访问的数据,就是覆盖time值虽小的数据。

代码

// Java版 import java.util.*; public class Solution { public int[] LRU (int[][] operators, int k) { if(operators.length==0){ return null; } Map<Integer,Integer> cache = new HashMap<>(); // 缓存 Map<Integer,Integer> readRecord = new HashMap<>(); // 缓存数据的访问记录 int cacheLen = 0; // 当前缓存大小 List<Integer> result = new ArrayList<>(); // 访问记录数据,越小代表越久未被访问 int time = 0; for(int i=0; i<operators.length; i++){ time++; if(operators[i][0]==1){ // 缓存未饱和 if(cache.isEmpty() || cache.size()<k){ // 数据存入缓存区 cache.put(operators[i][1],operators[i][2]); // 更新访问记录 readRecord.put(operators[i][1],time); }else { // 缓存饱和 // 获取最近未被访问的key Integer lastKey = null; Integer minValue = time; for(Integer key : readRecord.keySet()){ if(readRecord.get(key)<minValue){ minValue = readRecord.get(key); lastKey = key; } } // 溢出缓存中最近未被访问的数据 cache.remove(lastKey); // 移除访问记录 readRecord.remove(lastKey); // 插入新数据 cache.put(operators[i][1],operators[i][2]); readRecord.put(operators[i][1],time); } }else{ // 访问模式 if(cache.containsKey(operators[i][1])){ result.add(cache.get(operators[i][1])); readRecord.put(operators[i][1],time); }else{ result.add(-1); } } } int re[] = new int[result.size()]; for(int i=0; i<result.size(); i++){ re[i] = result.get(i).intValue(); } return re; } }

拓展

以上方法在处理小cache时比较有效,但是当cache非常大的时候,每次查询最近访问情况都是极大的资源消耗,所以在实际的计算器操作系统的缓存管理中,则使用循环链表来记录最近访问情况。牛人链接:https://www.iteye.com/blog/gogole-692103

最新回复(0)