{ "data": { "question": { "questionId": "460", "questionFrontendId": "460", "boundTopicId": null, "title": "LFU Cache", "titleSlug": "lfu-cache", "content": "
Design and implement a data structure for a Least Frequently Used (LFU) cache.
\n\nImplement the LFUCache
class:
LFUCache(int capacity)
Initializes the object with the capacity
of the data structure.int get(int key)
Gets the value of the key
if the key
exists in the cache. Otherwise, returns -1
.void put(int key, int value)
Update the value of the key
if present, or inserts the key
if not already present. When the cache reaches its capacity
, it should invalidate and remove the least frequently used key before inserting a new item. For this problem, when there is a tie (i.e., two or more keys with the same frequency), the least recently used key
would be invalidated.To determine the least frequently used key, a use counter is maintained for each key in the cache. The key with the smallest use counter is the least frequently used key.
\n\nWhen a key is first inserted into the cache, its use counter is set to 1
(due to the put
operation). The use counter for a key in the cache is incremented either a get
or put
operation is called on it.
The functions get
and put
must each run in O(1)
average time complexity.
\n
Example 1:
\n\n\nInput\n["LFUCache", "put", "put", "get", "put", "get", "get", "put", "get", "get", "get"]\n[[2], [1, 1], [2, 2], [1], [3, 3], [2], [3], [4, 4], [1], [3], [4]]\nOutput\n[null, null, null, 1, null, -1, 3, null, -1, 3, 4]\n\nExplanation\n// cnt(x) = the use counter for key x\n// cache=[] will show the last used order for tiebreakers (leftmost element is most recent)\nLFUCache lfu = new LFUCache(2);\nlfu.put(1, 1); // cache=[1,_], cnt(1)=1\nlfu.put(2, 2); // cache=[2,1], cnt(2)=1, cnt(1)=1\nlfu.get(1); // return 1\n // cache=[1,2], cnt(2)=1, cnt(1)=2\nlfu.put(3, 3); // 2 is the LFU key because cnt(2)=1 is the smallest, invalidate 2.\n // cache=[3,1], cnt(3)=1, cnt(1)=2\nlfu.get(2); // return -1 (not found)\nlfu.get(3); // return 3\n // cache=[3,1], cnt(3)=2, cnt(1)=2\nlfu.put(4, 4); // Both 1 and 3 have the same cnt, but 1 is LRU, invalidate 1.\n // cache=[4,3], cnt(4)=1, cnt(3)=2\nlfu.get(1); // return -1 (not found)\nlfu.get(3); // return 3\n // cache=[3,4], cnt(4)=1, cnt(3)=3\nlfu.get(4); // return 4\n // cache=[4,3], cnt(4)=2, cnt(3)=3\n\n\n
\n
Constraints:
\n\n0 <= capacity <= 104
0 <= key <= 105
0 <= value <= 109
2 * 105
calls will be made to get
and put
.\n ", "translatedTitle": null, "translatedContent": null, "isPaidOnly": false, "difficulty": "Hard", "likes": 3154, "dislikes": 206, "isLiked": null, "similarQuestions": "[{\"title\": \"LRU Cache\", \"titleSlug\": \"lru-cache\", \"difficulty\": \"Medium\", \"translatedTitle\": null}, {\"title\": \"Design In-Memory File System\", \"titleSlug\": \"design-in-memory-file-system\", \"difficulty\": \"Hard\", \"translatedTitle\": null}]", "exampleTestcases": "[\"LFUCache\",\"put\",\"put\",\"get\",\"put\",\"get\",\"get\",\"put\",\"get\",\"get\",\"get\"]\n[[2],[1,1],[2,2],[1],[3,3],[2],[3],[4,4],[1],[3],[4]]", "categoryTitle": "Algorithms", "contributors": [], "topicTags": [ { "name": "Hash Table", "slug": "hash-table", "translatedName": null, "__typename": "TopicTagNode" }, { "name": "Linked List", "slug": "linked-list", "translatedName": null, "__typename": "TopicTagNode" }, { "name": "Design", "slug": "design", "translatedName": null, "__typename": "TopicTagNode" }, { "name": "Doubly-Linked List", "slug": "doubly-linked-list", "translatedName": null, "__typename": "TopicTagNode" } ], "companyTagStats": null, "codeSnippets": [ { "lang": "C++", "langSlug": "cpp", "code": "class LFUCache {\npublic:\n LFUCache(int capacity) {\n \n }\n \n int get(int key) {\n \n }\n \n void put(int key, int value) {\n \n }\n};\n\n/**\n * Your LFUCache object will be instantiated and called as such:\n * LFUCache* obj = new LFUCache(capacity);\n * int param_1 = obj->get(key);\n * obj->put(key,value);\n */", "__typename": "CodeSnippetNode" }, { "lang": "Java", "langSlug": "java", "code": "class LFUCache {\n\n public LFUCache(int capacity) {\n \n }\n \n public int get(int key) {\n \n }\n \n public void put(int key, int value) {\n \n }\n}\n\n/**\n * Your LFUCache object will be instantiated and called as such:\n * LFUCache obj = new LFUCache(capacity);\n * int param_1 = obj.get(key);\n * obj.put(key,value);\n */", "__typename": "CodeSnippetNode" }, { "lang": "Python", "langSlug": "python", "code": "class LFUCache(object):\n\n def __init__(self, capacity):\n \"\"\"\n :type capacity: int\n \"\"\"\n \n\n def get(self, key):\n \"\"\"\n :type key: int\n :rtype: int\n \"\"\"\n \n\n def put(self, key, value):\n \"\"\"\n :type key: int\n :type value: int\n :rtype: None\n \"\"\"\n \n\n\n# Your LFUCache object will be instantiated and called as such:\n# obj = LFUCache(capacity)\n# param_1 = obj.get(key)\n# obj.put(key,value)", "__typename": "CodeSnippetNode" }, { "lang": "Python3", "langSlug": "python3", "code": "class LFUCache:\n\n def __init__(self, capacity: int):\n \n\n def get(self, key: int) -> int:\n \n\n def put(self, key: int, value: int) -> None:\n \n\n\n# Your LFUCache object will be instantiated and called as such:\n# obj = LFUCache(capacity)\n# param_1 = obj.get(key)\n# obj.put(key,value)", "__typename": "CodeSnippetNode" }, { "lang": "C", "langSlug": "c", "code": "\n\n\ntypedef struct {\n \n} LFUCache;\n\n\nLFUCache* lFUCacheCreate(int capacity) {\n \n}\n\nint lFUCacheGet(LFUCache* obj, int key) {\n \n}\n\nvoid lFUCachePut(LFUCache* obj, int key, int value) {\n \n}\n\nvoid lFUCacheFree(LFUCache* obj) {\n \n}\n\n/**\n * Your LFUCache struct will be instantiated and called as such:\n * LFUCache* obj = lFUCacheCreate(capacity);\n * int param_1 = lFUCacheGet(obj, key);\n \n * lFUCachePut(obj, key, value);\n \n * lFUCacheFree(obj);\n*/", "__typename": "CodeSnippetNode" }, { "lang": "C#", "langSlug": "csharp", "code": "public class LFUCache {\n\n public LFUCache(int capacity) {\n \n }\n \n public int Get(int key) {\n \n }\n \n public void Put(int key, int value) {\n \n }\n}\n\n/**\n * Your LFUCache object will be instantiated and called as such:\n * LFUCache obj = new LFUCache(capacity);\n * int param_1 = obj.Get(key);\n * obj.Put(key,value);\n */", "__typename": "CodeSnippetNode" }, { "lang": "JavaScript", "langSlug": "javascript", "code": "/**\n * @param {number} capacity\n */\nvar LFUCache = function(capacity) {\n \n};\n\n/** \n * @param {number} key\n * @return {number}\n */\nLFUCache.prototype.get = function(key) {\n \n};\n\n/** \n * @param {number} key \n * @param {number} value\n * @return {void}\n */\nLFUCache.prototype.put = function(key, value) {\n \n};\n\n/** \n * Your LFUCache object will be instantiated and called as such:\n * var obj = new LFUCache(capacity)\n * var param_1 = obj.get(key)\n * obj.put(key,value)\n */", "__typename": "CodeSnippetNode" }, { "lang": "Ruby", "langSlug": "ruby", "code": "class LFUCache\n\n=begin\n :type capacity: Integer\n=end\n def initialize(capacity)\n \n end\n\n\n=begin\n :type key: Integer\n :rtype: Integer\n=end\n def get(key)\n \n end\n\n\n=begin\n :type key: Integer\n :type value: Integer\n :rtype: Void\n=end\n def put(key, value)\n \n end\n\n\nend\n\n# Your LFUCache object will be instantiated and called as such:\n# obj = LFUCache.new(capacity)\n# param_1 = obj.get(key)\n# obj.put(key, value)", "__typename": "CodeSnippetNode" }, { "lang": "Swift", "langSlug": "swift", "code": "\nclass LFUCache {\n\n init(_ capacity: Int) {\n \n }\n \n func get(_ key: Int) -> Int {\n \n }\n \n func put(_ key: Int, _ value: Int) {\n \n }\n}\n\n/**\n * Your LFUCache object will be instantiated and called as such:\n * let obj = LFUCache(capacity)\n * let ret_1: Int = obj.get(key)\n * obj.put(key, value)\n */", "__typename": "CodeSnippetNode" }, { "lang": "Go", "langSlug": "golang", "code": "type LFUCache struct {\n \n}\n\n\nfunc Constructor(capacity int) LFUCache {\n \n}\n\n\nfunc (this *LFUCache) Get(key int) int {\n \n}\n\n\nfunc (this *LFUCache) Put(key int, value int) {\n \n}\n\n\n/**\n * Your LFUCache object will be instantiated and called as such:\n * obj := Constructor(capacity);\n * param_1 := obj.Get(key);\n * obj.Put(key,value);\n */", "__typename": "CodeSnippetNode" }, { "lang": "Scala", "langSlug": "scala", "code": "class LFUCache(_capacity: Int) {\n\n def get(key: Int): Int = {\n \n }\n\n def put(key: Int, value: Int) {\n \n }\n\n}\n\n/**\n * Your LFUCache object will be instantiated and called as such:\n * var obj = new LFUCache(capacity)\n * var param_1 = obj.get(key)\n * obj.put(key,value)\n */", "__typename": "CodeSnippetNode" }, { "lang": "Kotlin", "langSlug": "kotlin", "code": "class LFUCache(capacity: Int) {\n\n fun get(key: Int): Int {\n \n }\n\n fun put(key: Int, value: Int) {\n \n }\n\n}\n\n/**\n * Your LFUCache object will be instantiated and called as such:\n * var obj = LFUCache(capacity)\n * var param_1 = obj.get(key)\n * obj.put(key,value)\n */", "__typename": "CodeSnippetNode" }, { "lang": "Rust", "langSlug": "rust", "code": "struct LFUCache {\n\n}\n\n\n/** \n * `&self` means the method takes an immutable reference.\n * If you need a mutable reference, change it to `&mut self` instead.\n */\nimpl LFUCache {\n\n fn new(capacity: i32) -> Self {\n \n }\n \n fn get(&self, key: i32) -> i32 {\n \n }\n \n fn put(&self, key: i32, value: i32) {\n \n }\n}\n\n/**\n * Your LFUCache object will be instantiated and called as such:\n * let obj = LFUCache::new(capacity);\n * let ret_1: i32 = obj.get(key);\n * obj.put(key, value);\n */", "__typename": "CodeSnippetNode" }, { "lang": "PHP", "langSlug": "php", "code": "class LFUCache {\n /**\n * @param Integer $capacity\n */\n function __construct($capacity) {\n \n }\n \n /**\n * @param Integer $key\n * @return Integer\n */\n function get($key) {\n \n }\n \n /**\n * @param Integer $key\n * @param Integer $value\n * @return NULL\n */\n function put($key, $value) {\n \n }\n}\n\n/**\n * Your LFUCache object will be instantiated and called as such:\n * $obj = LFUCache($capacity);\n * $ret_1 = $obj->get($key);\n * $obj->put($key, $value);\n */", "__typename": "CodeSnippetNode" }, { "lang": "TypeScript", "langSlug": "typescript", "code": "class LFUCache {\n constructor(capacity: number) {\n\n }\n\n get(key: number): number {\n\n }\n\n put(key: number, value: number): void {\n\n }\n}\n\n/**\n * Your LFUCache object will be instantiated and called as such:\n * var obj = new LFUCache(capacity)\n * var param_1 = obj.get(key)\n * obj.put(key,value)\n */", "__typename": "CodeSnippetNode" }, { "lang": "Racket", "langSlug": "racket", "code": "(define lfu-cache%\n (class object%\n (super-new)\n\n ; capacity : exact-integer?\n (init-field\n capacity)\n \n ; get : exact-integer? -> exact-integer?\n (define/public (get key)\n\n )\n ; put : exact-integer? exact-integer? -> void?\n (define/public (put key value)\n\n )))\n\n;; Your lfu-cache% object will be instantiated and called as such:\n;; (define obj (new lfu-cache% [capacity capacity]))\n;; (define param_1 (send obj get key))\n;; (send obj put key value)", "__typename": "CodeSnippetNode" }, { "lang": "Erlang", "langSlug": "erlang", "code": "-spec lfu_cache_init_(Capacity :: integer()) -> any().\nlfu_cache_init_(Capacity) ->\n .\n\n-spec lfu_cache_get(Key :: integer()) -> integer().\nlfu_cache_get(Key) ->\n .\n\n-spec lfu_cache_put(Key :: integer(), Value :: integer()) -> any().\nlfu_cache_put(Key, Value) ->\n .\n\n\n%% Your functions will be called as such:\n%% lfu_cache_init_(Capacity),\n%% Param_1 = lfu_cache_get(Key),\n%% lfu_cache_put(Key, Value),\n\n%% lfu_cache_init_ will be called before every test case, in which you can do some necessary initializations.", "__typename": "CodeSnippetNode" }, { "lang": "Elixir", "langSlug": "elixir", "code": "defmodule LFUCache do\n @spec init_(capacity :: integer) :: any\n def init_(capacity) do\n\n end\n\n @spec get(key :: integer) :: integer\n def get(key) do\n\n end\n\n @spec put(key :: integer, value :: integer) :: any\n def put(key, value) do\n\n end\nend\n\n# Your functions will be called as such:\n# LFUCache.init_(capacity)\n# param_1 = LFUCache.get(key)\n# LFUCache.put(key, value)\n\n# LFUCache.init_ will be called before every test case, in which you can do some necessary initializations.", "__typename": "CodeSnippetNode" } ], "stats": "{\"totalAccepted\": \"151K\", \"totalSubmission\": \"383.6K\", \"totalAcceptedRaw\": 150995, \"totalSubmissionRaw\": 383618, \"acRate\": \"39.4%\"}", "hints": [], "solution": null, "status": null, "sampleTestCase": "[\"LFUCache\",\"put\",\"put\",\"get\",\"put\",\"get\",\"get\",\"put\",\"get\",\"get\",\"get\"]\n[[2],[1,1],[2,2],[1],[3,3],[2],[3],[4,4],[1],[3],[4]]", "metaData": "{\r\n \"classname\": \"LFUCache\",\r\n \"maxbytesperline\": 200000,\r\n \"constructor\": {\r\n \"params\": [\r\n {\r\n \"type\": \"integer\",\r\n \"name\": \"capacity\"\r\n }\r\n ]\r\n },\r\n \"methods\": [\r\n {\r\n \"name\" : \"get\",\r\n \"params\": [\r\n {\r\n \"type\": \"integer\",\r\n \"name\": \"key\"\r\n }\r\n ],\r\n \"return\": {\r\n \"type\": \"integer\"\r\n }\r\n },\r\n {\r\n \"name\" : \"put\",\r\n \"params\": [\r\n {\r\n \"type\": \"integer\",\r\n \"name\": \"key\"\r\n },\r\n {\r\n \"type\": \"integer\",\r\n \"name\": \"value\"\r\n }\r\n ],\r\n \"return\": {\r\n \"type\": \"void\"\r\n }\r\n }\r\n ],\r\n \"systemdesign\": true,\r\n \"params\": [\r\n {\r\n \"name\": \"inputs\",\r\n \"type\": \"integer[]\"\r\n },\r\n {\r\n \"name\": \"inputs\",\r\n \"type\": \"integer[]\"\r\n }\r\n ],\r\n \"return\": {\r\n \"type\": \"list
Compiled with clang 11
using the latest C++ 17 standard.
Your code is compiled with level two optimization (-O2
). AddressSanitizer is also enabled to help detect out-of-bounds and use-after-free bugs.
Most standard library headers are already included automatically for your convenience.
\"], \"java\": [\"Java\", \" OpenJDK 17
. Java 8 features such as lambda expressions and stream API can be used.
Most standard library headers are already included automatically for your convenience.
\\r\\nIncludes Pair
class from https://docs.oracle.com/javase/8/javafx/api/javafx/util/Pair.html.
Python 2.7.12
.
Most libraries are already imported automatically for your convenience, such as array, bisect, collections. If you need more libraries, you can import it yourself.
\\r\\n\\r\\nFor Map/TreeMap data structure, you may use sortedcontainers library.
\\r\\n\\r\\nNote that Python 2.7 will not be maintained past 2020. For the latest Python, please choose Python3 instead.
\"], \"c\": [\"C\", \"Compiled with gcc 8.2
using the gnu99 standard.
Your code is compiled with level one optimization (-O1
). AddressSanitizer is also enabled to help detect out-of-bounds and use-after-free bugs.
Most standard library headers are already included automatically for your convenience.
\\r\\n\\r\\nFor hash table operations, you may use uthash. \\\"uthash.h\\\" is included by default. Below are some examples:
\\r\\n\\r\\n1. Adding an item to a hash.\\r\\n
\\r\\nstruct hash_entry {\\r\\n int id; /* we'll use this field as the key */\\r\\n char name[10];\\r\\n UT_hash_handle hh; /* makes this structure hashable */\\r\\n};\\r\\n\\r\\nstruct hash_entry *users = NULL;\\r\\n\\r\\nvoid add_user(struct hash_entry *s) {\\r\\n HASH_ADD_INT(users, id, s);\\r\\n}\\r\\n\\r\\n\\r\\n\\r\\n
2. Looking up an item in a hash:\\r\\n
\\r\\nstruct hash_entry *find_user(int user_id) {\\r\\n struct hash_entry *s;\\r\\n HASH_FIND_INT(users, &user_id, s);\\r\\n return s;\\r\\n}\\r\\n\\r\\n\\r\\n\\r\\n
3. Deleting an item in a hash:\\r\\n
\\r\\nvoid delete_user(struct hash_entry *user) {\\r\\n HASH_DEL(users, user); \\r\\n}\\r\\n\\r\\n\"], \"csharp\": [\"C#\", \"\\r\\n\\r\\n
Your code is compiled with debug flag enabled (/debug
).
Node.js 16.13.2
.
Your code is run with --harmony
flag, enabling new ES6 features.
lodash.js library is included by default.
\\r\\n\\r\\nFor Priority Queue / Queue data structures, you may use datastructures-js/priority-queue and datastructures-js/queue.
\"], \"ruby\": [\"Ruby\", \"Ruby 3.1
Some common data structure implementations are provided in the Algorithms module: https://www.rubydoc.info/github/kanwei/algorithms/Algorithms
\"], \"swift\": [\"Swift\", \"Swift 5.5.2
.
Go 1.17.6
.
Support https://godoc.org/github.com/emirpasic/gods library.
\"], \"python3\": [\"Python3\", \"Python 3.10
.
Most libraries are already imported automatically for your convenience, such as array, bisect, collections. If you need more libraries, you can import it yourself.
\\r\\n\\r\\nFor Map/TreeMap data structure, you may use sortedcontainers library.
\"], \"scala\": [\"Scala\", \"Scala 2.13.7
.
Kotlin 1.3.10
.
Rust 1.58.1
Supports rand v0.6\\u00a0from crates.io
\"], \"php\": [\"PHP\", \"PHP 8.1
.
With bcmath module
\"], \"typescript\": [\"Typescript\", \"TypeScript 4.5.4, Node.js 16.13.2
.
Your code is run with --harmony
flag, enabling new ES2020 features.
lodash.js library is included by default.
\"], \"racket\": [\"Racket\", \"Run with Racket 8.3
.