LFU緩存
阿新 • • 發佈:2018-04-13
lee 復雜度 leetcode println -c add https 時間復雜度 AI
https://leetcode-cn.com/problems/lfu-cache/description/
緩存的實現可以采取多種策略,不同策略優點的評估就是“命中率”。好的策略可以實現較高的命中率。常用的策略如:LRU(最近最少使用)、LFU(最不頻繁使用)。這兩種策略都可以在O(1)時間內實現get和put。本文主要講講LFU的實現。
import java.util.HashMap; import java.util.LinkedHashSet; class LFUCache { public int capacity;//容量大小 public HashMap<Integer, Integer> map = new HashMap<>();//存儲put進去的key和value public HashMap<Integer, Integer> frequent = new HashMap<>();//存儲每個key的頻率值 //存儲每個頻率的相應的key的值的集合,這裏用HashSet是因為其是由HashMap底層實現的,可以O(1)時間復雜度查找元素 //而且linked是有序的,同一頻率值越往後越最近訪問 public HashMap<Integer, LinkedHashSet<Integer>> list = new HashMap<>(); int min = -1;//標記當前頻率中的最小值 public LFUCache(int capacity) { this.capacity = capacity; } public int get(int key) { if(!map.containsKey(key)){ return -1; }else{ int value = map.get(key);//獲取元素的value值 int count = frequent.get(key); frequent.put(key, count + 1); list.get(count).remove(key);//先移除當前key //更改min的值 if(count == min && list.get(count).size() == 0) min++; LinkedHashSet<Integer> set = list.containsKey(count + 1) ? list.get(count + 1) : new LinkedHashSet<Integer>(); set.add(key); list.put(count + 1, set); return value; } } public void put(int key, int value) { if(capacity <= 0){ return; } //這一塊跟get的邏輯一樣 if(map.containsKey(key)){ map.put(key, value); int count = frequent.get(key); frequent.put(key, count + 1); list.get(count).remove(key);//先移除當前key //更改min的值 if (count == min && list.get(count).size() == 0) min++; LinkedHashSet<Integer> set = list.containsKey(count + 1) ? list.get(count + 1) : new LinkedHashSet<Integer>(); set.add(key); list.put(count + 1, set); }else{ if(map.size() >= capacity){ Integer removeKey = list.get(min).iterator().next(); list.get(min).remove(removeKey); map.remove(removeKey); frequent.remove(removeKey); } map.put(key, value); frequent.put(key, 1); LinkedHashSet<Integer> set = list.containsKey(1) ? list.get(1) : new LinkedHashSet<Integer>(); set.add(key); list.put(1, set); min = 1; } } public static void main(String[] args) { LFUCache lfuCache = new LFUCache(2); lfuCache.put(2, 1); lfuCache.put(3, 2); System.out.println(lfuCache.get(3)); System.out.println(lfuCache.get(2)); lfuCache.put(4, 3); System.out.println(lfuCache.get(2)); System.out.println(lfuCache.get(3)); System.out.println(lfuCache.get(4)); } }
參考資料
http://www.cnblogs.com/DarrenChan/p/8819996.html
LFU緩存