[Leetcode] 460. LFU cache Most infrequently used page substitution buffers

Source: Internet
Author: User
Tags prev

Design and implement a data structure for Least frequently Used (LFU) cache. It should support the following operations: get and put .

get(key)-Get The value ('ll always be positive) of the key if the key exists in the cache, otherwise return-1.
put(key, value)-Set or insert the value if the key is not already present. When the cache is reaches its capacity, it should invalidate the least frequently used item before inserting a new item. For the purpose of this problem, when there is a tie (i.e., b or more keys, which has the same frequency), the least rece Ntly used key would be evicted.

Follow up:
Could do both operations in O (1) time complexity?

Example:

Lfucache cache = new Lfucache (2/* capacity *); Cache.put (1, 1); Cache.put (2, 2); Cache.get (1);       Returns 1cache.put (3, 3);    Evicts key 2cache.get (2);       Returns-1 (not found) Cache.get (3);       Returns 3.cache.put (4, 4);    Evicts key 1.cache.get (1);       Returns-1 (not found) Cache.get (3);       Returns 3cache.get (4);       Returns 4

Doubly linked list (doubly Linked list) + hash table (hash table)

Java:

public class Lfucache {Node head = null;    final int capacity;    Map<integer, integer> ValueMap;    Map<integer, node> Nodemap;        public Lfucache (int capacity) {this.capacity = capacity;        ValueMap = new Hashmap<> (this.capacity, 1f);    Nodemap = new Hashmap<> (this.capacity, 1f);        } public int get (int key) {if (Valuemap.containskey (key)) Increase (key, Valuemap.get (key));    Return Valuemap.getordefault (Key,-1);        } private void increase (int key, int value) {node node = nodemap.get (key);        Node.keys.remove (key);        if (Objects.isnull (node.next)) Node.next = new node (node, NULL, 1 + node.count, key);        else if (Node.next.count = = Node.count + 1) node.next.keys.add (key);        else Node.next = Node.next.prev = new node (node, Node.next, Node.count + 1, key);        Nodemap.put (key, Node.next);        Valuemap.put (key, value);    if (Node.keys.isEmpty ()) Remove (node); } private void RemovE (node node) {if (head = = Node) head = Node.next;        else Node.prev.next = Node.next;    if (Objects.nonnull (node.next)) Node.next.prev = Node.prev;        } public void set (int key, int value) {if (0 = = this.capacity) return;        if (Valuemap.containskey (key)) {Increase (key, value);            } else {if (valuemap.size () = = this.capacity) remove ();            Valuemap.put (key, value);        Add (key);        }} private void Add (int key) {if (Objects.isnull (head)) head = new Node (null, NULL, 1, key);        else if (Head.count = = 1) head.keys.add (key);        else head = Head.prev = new Node (null, head, 1, key);    Nodemap.put (key, head);        } private void Remove () {if (Objects.isnull (head)) return;        int oldest = Head.keys.iterator (). Next ();        Head.keys.remove (oldest);        if (Head.keys.isEmpty ()) remove (head);        Nodemap.remove (oldest);    Valuemap.remove (oldest); } class Node {        Public Node prev, next;        public final int count;        Public linkedhashset<integer> keys = new linkedhashset<> ();            Public node (node prev, node next, int count, int key) {This.prev = prev;            This.next = Next;            This.count = count;        Keys.add (key);  }    }}

Python:

Class Keynode (object): Def __init__ (self, key, value, Freq = 1): Self.key = key Self.value = value        Self.freq = Freq Self.prev = Self.next = Noneclass Freqnode (object): Def __init__ (self, freq, prev, next): Self.freq = freq Self.prev = prev Self.next = Next Self.first = Self.last = Noneclass Lfucache (obj ECT): def __init__ (self, capacity): "" ": Type Capacity:int" "" "self.capacity = Cap         Acity self.keydict = dict () self.freqdict = Dict () Self.head = None def get (self, Key): "" "             : Type Key:int:rtype:int "" "if key in Self.keyDict:keyNode = Self.keydict[key] Value = Keynode.value self.increase (key, value) return value Return-1 def set (Self, key, value): ' "": Type Key:int:type value:int:rtype:void "" "if self         . Capacity = = 0:   return if key in Self.keyDict:self.increase (key, value) return if Len (self.keydict ) = = Self.capacity:self.removeKeyNode (self.head.last) Self.insertkeynode (key, value) def increase (SE        LF, key, value): "" "increments the freq of an existing Keynode<key, value> by 1. : Type Key:str:rtype:void "" "Keynode = Self.keydict[key] Keynode.value = value freqn Ode = self.freqdict[keynode.freq] Nextfreqnode = freqnode.next Keynode.freq + = 1 if Nextfreqnode is N        One or Nextfreqnode.freq > KeyNode.freq:nextFreqNode = Self.insertfreqnodeafter (Keynode.freq, Freqnode)        Self.unlinkkey (Keynode, Freqnode) Self.linkkey (Keynode, Nextfreqnode) def insertkeynode (self, Key, value):        "" "Inserts a new Keynode<key, value> with Freq 1. : Type Key:str:rtype:void "" "Keynode = self.keydict[key] = Keynode (key, value) Freqnode = Self.freqDict.get (1) if freqnode is None:freqnode = Self.freqdic  T[1] = Freqnode (1, None, self.head) If Self.head:self.head.prev = Freqnode self.head        = Freqnode Self.linkkey (Keynode, Freqnode) def delfreqnode (self, Freqnode): "" "Delete Freqnode.  : Rtype:void "" "prev, next = Freqnode.prev, freqnode.next if Prev:prev.next = Next If Next:next.prev = prev if Self.head = = FreqNode:self.head = Next del self.freqdict[freqnode.freq] def i        Nsertfreqnodeafter (self, Freq, node): "" "Inserts a new Freqnode (Freq) after node. : Rtype:freqnode "" "NewNode = Freqnode (freq, node, node.next) Self.freqdict[freq] = NewNode I F Node.next:node.next.prev = NewNode Node.next = newNode return NewNode def removekeynode (self, Keynode) : "" "Remove Keynode:Rtype:void "" "Self.unlinkkey (Keynode, Self.freqdict[keynode.freq]) del Self.keydict[keynode.key]        def unlinkkey (self, Keynode, Freqnode): "" "Unlink Keynode from FreqNode:rtype:void" " Next, prev = Keynode.next, keynode.prev if Prev:prev.next = next if Next:next.prev = prev If fr Eqnode.first = = KeyNode:freqNode.first = Next if Freqnode.last = = KeyNode:freqNode.last = prev If freqnode . First is None:self.delFreqNode (Freqnode) def linkkey (self, Keynode, Freqnode): "" "Link Keynode to Freq Node:rtype:void "" "Firstkeynode = Freqnode.first Keynode.prev = None Keynode.next = Firstkeynode if FirstKeyNode:firstKeyNode.prev = Keynode Freqnode.first = Keynode if Freqnode.last i s None:freqNode.last = keynode# Your Lfucache object would be instantiated and called as such:# obj = Lfucache (capacity) # Param_1 = Obj.get (key) #Obj.set (Key,value)   

Python:

Class Cachenode (object): Def __init__ (self, key, value, Freq_node, Pre, NXT): Self.key = key Self.value =     Value Self.freq_node = Freq_node Self.pre = Pre # previous Cachenode self.nxt = nxt # next Cachenode def free_myself (self): if Self.freq_node.cache_head = = SELF.FREQ_NODE.CACHE_TAIL:SELF.FREQ_NODE.CAC            He_head = Self.freq_node.cache_tail = None elif Self.freq_node.cache_head = = Self:self.nxt.pre = None Self.freq_node.cache_head = self.nxt elif Self.freq_node.cache_tail = = SELF:SELF.PRE.NXT = No  Ne self.freq_node.cache_tail = self.pre else:self.pre.nxt = self.nxt self.nxt.pre = Self.pre Self.pre = None Self.nxt = None Self.freq_node = Noneclass Freqnode (object): Def __ini T__ (self, freq, Pre, NXT): Self.freq = freq Self.pre = Pre # previous Freqnode self.nxt = NXT # Next Freqnode SELF.CACHe_head = none # Cachenode head under this freqnode self.cache_tail = None # Cachenode tail under this Freqnode def count_caches (self): If self.cache_head are None and Self.cache_tail is None:return 0 elif sel F.cache_head = = Self.cache_tail:return 1 Else:return ' "def" Remove (self): if SE        Lf.pre is not None:self.pre.nxt = SELF.NXT if self.nxt are not None:self.nxt.pre = Self.pre Pre = Self.pre NXT = self.nxt Self.pre = self.nxt = Self.cache_head = Self.cache_tail = None r Eturn (Pre, NXT) def pop_head_cache (self): If self.cache_head are None and Self.cache_tail is None:re Turn None elif Self.cache_head = = Self.cache_tail:cache_head = Self.cache_head self.cache_he AD = Self.cache_tail = None return Cache_head else:cache_head = Self.cache_head s Elf.cache_head.nxt.pre = None self.cache_head = self.cache_head.nxt return cache_head def append_cache_to_tail (self, Cach E_node): Cache_node.freq_node = self if self.cache_head are None and Self.cache_tail is none:self . Cache_head = Self.cache_tail = Cache_node Else:cache_node.pre = Self.cache_tail Cache_node. NXT = None SELF.CACHE_TAIL.NXT = Cache_node Self.cache_tail = Cache_node def insert_after_me (self , freq_node): Freq_node.pre = self FREQ_NODE.NXT = SELF.NXT If self.nxt are not none:self. Nxt.pre = Freq_node self.nxt = Freq_node def insert_before_me (self, freq_node): If Self.pre is no T None:self.pre.nxt = freq_node Freq_node.pre = self.pre freq_node.nxt = Self sel F.pre = Freq_node class Lfucache (object): Def __init__ (self, capacity): Self.cache = {} # {Key:cache_nod e} self.capacity= Capacity Self.freq_link_head = None def get (self, key): If key in Self.cache:cache_node = Self.cache[key] Freq_node = cache_node.freq_node value = Cache_node.value Self.move_fo        Rward (Cache_node, Freq_node) return value else:return-1 def set (self, key, value): If self.capacity <= 0:return-1 if key not in Self.cache:if Len (self.cache) &G t;= Self.capacity:self.dump_cache () Self.create_cache (key, value) Else:cache _node = Self.cache[key] Freq_node = Cache_node.freq_node Cache_node.value = value Self.mo Ve_forward (Cache_node, Freq_node) def move_forward (self, Cache_node, Freq_node): If FREQ_NODE.NXT is None or fre Q_node.nxt.freq! = freq_node.freq + 1:target_freq_node = Freqnode (Freq_node.freq + 1, none, none) t      Arget_empty = True  Else:target_freq_node = freq_node.nxt Target_empty = False cache_node.free_myself ( ) Target_freq_node.append_cache_to_tail (Cache_node) if Target_empty:freq_node.insert_after_me (Ta Rget_freq_node) if freq_node.count_caches () = = 0:if Self.freq_link_head = = Freq_node:se Lf.freq_link_head = Target_freq_node freq_node.remove () def dump_cache (self): Head_freq_node = Self.f Req_link_head Self.cache.pop (Head_freq_node.cache_head.key) Head_freq_node.pop_head_cache () if Head_f Req_node.count_caches () = = 0:self.freq_link_head = Head_freq_node.nxt head_freq_node.remove () de F Create_cache (self, Key, value): Cache_node = Cachenode (key, value, none, none, none) self.cache[key] = CAC He_node if Self.freq_link_head is None or self.freq_link_head.freq! = 0:new_freq_node = Freqnod        E (0, none, none)    New_freq_node.append_cache_to_tail (Cache_node) If Self.freq_link_head is not None:self.freq            _link_head.insert_before_me (new_freq_node) Self.freq_link_head = New_freq_node Else: Self.freq_link_head.append_cache_to_tail (Cache_node)

C + +:

Class Lfucache {public:lfucache (int capacity) {cap = capacity;        } int get (int key) {if (M.count (key) = = 0) return-1;        Freq[m[key].second].erase (Iter[key]);        ++m[key].second;        Freq[m[key].second].push_back (key);        Iter[key] =--freq[m[key].second].end ();        if (freq[minfreq].size () = = 0) ++minfreq;    return m[key].first;        } void put (int key, int value) {if (Cap <= 0) return;            if (Get (key)! =-1) {M[key].first = value;        Return            } if (M.size () >= cap) {m.erase (Freq[minfreq].front ());            Iter.erase (Freq[minfreq].front ());        Freq[minfreq].pop_front ();        } M[key] = {value, 1};        Freq[1].push_back (key);        Iter[key] =--freq[1].end ();    Minfreq = 1;    }private:int cap, Minfreq;    Unordered_map<int, Pair<int, int>> m;    Unordered_map<int, list<int>> freq; Unordered_map<int, List<int>::iterator> iter;}; 

  

[Leetcode] 146. LRU Cache uses least recent caches

  

[Leetcode] 460. LFU cache Most infrequently used page substitution buffers

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.