LFU缓存结构设计

LFU缓存结构设计

题目描述

一个缓存结构需要实现如下功能。

set(key, value):将记录(key, value)插入该结构
get(key):返回key对应的value值 

但是缓存结构中最多放K条记录,如果新的第K+1条记录要加入,就需要根据策略删掉一条记录,然后才能把新记录加入。这个策略为:在缓存结构的K条记录中,哪一个key从进入缓存结构的时刻开始,被调用set或者get的次数最少,就删掉这个key的记录;
如果调用次数最少的key有多个,上次调用发生最早的key被删除
这就是LFU缓存替换算法。实现这个结构,K作为参数给出
[要求]
set和get方法的时间复杂度为O(1)

若opt=1,接下来两个整数x, y,表示set(x, y)
若opt=2,接下来一个整数x,表示get(x),若x未出现过或已被移除,则返回-1

对于每个操作2,输出一个答案

代码

import java.util.*;


public class Solution {
    /**
     * lfu design
     * @param operators int整型二维数组 ops
     * @param k int整型 the k
     * @return int整型一维数组
     */
    public int[] LFU (int[][] operators, int k) {
        LFUCache cache = new LFUCache(k);
        ArrayList<Integer> res = new ArrayList<>();
        for (int i = 0; i < operators.length; i++){
            if (operators[i][0] == 1){
                cache.put(operators[i][1], operators[i][2]);
            }else{
                res.add(cache.get(operators[i][1]));
            }
        }
        int[] ans = new int[res.size()];
        for (int i = 0; i < ans.length; i++){
            ans[i] = res.get(i);
        }
        return ans;
    }
    
    public class LFUCache{
        //建立节点,存储每个键值对的使用次数
        class Node{
            int key;
            int val;
            int freq;
            public Node(int key, int val, int freq){
                this.key = key;
                this.val = val;
                this.freq = freq;
            }
        }
        private int capacity;
        private int minFreq;
        //键值对
        private Map<Integer, Node> map = new HashMap<>();
        //<次数,使用次数x的Node链表>
        private Map<Integer, LinkedList<Node>> freqMap = new HashMap<>();
            
        public LFUCache(int capacity){
            this.capacity = capacity;
            this.minFreq = 1;
        }
            
        public void update(Node node){
            //更新Node在freq的次数链表的位置
            LinkedList<Node> list = freqMap.get(node.freq);
            list.remove(node);
            //判断之前次数的链表是否存在
            if(list.isEmpty() && node.freq == minFreq) minFreq++;
            //更新节点的使用次数    
            node.freq++;
            //更新Node在freqMap中次数链表的位置
            if(!freqMap.containsKey(node.freq)) freqMap.put(node.freq, new LinkedList<>());
            freqMap.get(node.freq).addLast(node);
       }
            
       public int get(int key){
            if(!map.containsKey(key)) return -1;
                
            Node node = map.get(key);
            update(node);
            return node.val;
       }
            
       public void put(int key, int val){
           //判断是否已经存在Node,存在就更新节点的使用次数
           if(map.containsKey(key)){
                 Node node = map.get(key);
                 update(node);
                 return;
            }
            //判断缓存是否满了,满了就删除使用次数最少的Node,并更新freqMap   
            if(map.size() >= capacity){
                 Node node = freqMap.get(minFreq).removeFirst();
                 map.remove(node.key);
             }
             //增添新节点,并更新minFreq,freqMap   
             Node node = new Node(key, val, 1);
             map.put(key, node);
             if (!freqMap.containsKey(1)){
                 freqMap.put(1, new LinkedList<>());
             }
             freqMap.get(1).addLast(node);
             minFreq = 1;
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值