[Swift]LeetCode460. LFU缓存 | LFU Cache
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
➤微信公众号:山青咏芝(shanqingyongzhi)
➤博客园地址:山青咏芝(https://www.cnblogs.com/strengthen/)
➤GitHub地址:https://github.com/strengthen/LeetCode
➤原文地址:https://www.cnblogs.com/strengthen/p/10816306.html
➤如果链接不是山青咏芝的博客园地址,则可能是爬取作者的文章。
➤原文已修改更新!强烈建议点击原文地址阅读!支持作者!支持原创!
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
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 (will 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 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., two or more keys that have the same frequency), the least recently used key would be evicted.
Follow up:
Could you 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 1 cache.put(3, 3); // evicts key 2 cache.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 3 cache.get(4); // returns 4
设计并实现最不经常使用(LFU)缓存的数据结构。它应该支持以下操作:get
和 put
。
get(key)
- 如果键存在于缓存中,则获取键的值(总是正数),否则返回 -1。put(key, value)
- 如果键不存在,请设置或插入值。当缓存达到其容量时,它应该在插入新项目之前,使最不经常使用的项目无效。在此问题中,当存在平局(即两个或更多个键具有相同使用频率)时,最近最少使用的键将被去除。
进阶:
你是否可以在 O(1) 时间复杂度内执行两项操作?
示例:
LFUCache cache = new LFUCache( 2 /* capacity (缓存容量) */ ); cache.put(1, 1); cache.put(2, 2); cache.get(1); // 返回 1 cache.put(3, 3); // 去除 key 2 cache.get(2); // 返回 -1 (未找到key 2) cache.get(3); // 返回 3 cache.put(4, 4); // 去除 key 1 cache.get(1); // 返回 -1 (未找到 key 1) cache.get(3); // 返回 3 cache.get(4); // 返回 4
1 import Foundation 2 class LFUCache { 3 //最大容量 4 var capacity:Int 5 //当前容量 6 var size:Int 7 // key 对应的node node是在小链表上面的 8 var kNMap:[Int:Node] 9 //Node对应的NodeList的头是哪个 就是任何一个小结点都能查到在大链表的哪个小链表上 10 //一个链表对应的大链表的结点是哪个 11 var heads:[Node:NodeList] 12 //整个大链表的头部 动态的头部 不一定就是1作为头 13 var headList:NodeList? 14 15 init(_ capacity: Int) { 16 self.capacity = capacity 17 self.size = 0 18 kNMap = [Int:Node]() 19 heads = [Node:NodeList]() 20 headList = nil 21 } 22 23 func get(_ key: Int) -> Int { 24 //特判一下 25 if capacity == 0 {return -1} 26 if kNMap[key] == nil {return -1} 27 //获取结点所在的原来的链表 28 if let node:Node = kNMap[key] 29 { 30 node.times += 1 31 //找到这个结点属于的小链表 32 if let curNodeList:NodeList = heads[node] 33 { 34 move(node, curNodeList) 35 } 36 //返回对应的node的值 37 return node.val 38 } 39 return -1 40 } 41 42 func put(_ key: Int, _ val: Int) { 43 //注意特判 44 if capacity == 0 {return} 45 //如果已经存在 就要更新值 46 if kNMap[key] != nil 47 { 48 let node:Node = kNMap[key]! 49 node.val = val 50 node.times += 1 51 //找到属于哪一个大链表 52 53 if let curNodeList = heads[node] 54 { 55 /** 56 * move方法 57 * 就是在一个大链表中,和自己的上下级解耦,然后放到下一个词频链表中 58 * 比如说现在是5 times链上的,则从5times链中拿出来,如果6存在,放到6times链的头部(头插法) 59 * 如果6不存在,建出6times的链表 60 */ 61 move(node, curNodeList) 62 } 63 } 64 //kNMap中不存在,是新插入的 没包含 65 else 66 { 67 //要先判断容量够不够,已经满了 要删掉一个结点 68 if size == capacity 69 { 70 //要删掉的就是作为大链表的 头部的尾结点 (次数最少的 用了最久的) 71 if let deNode = headList?.tail 72 { 73 headList?.deleteNode(deNode) 74 /** 75 * 如果我删掉了 这个deNode 有可能我整个大链表的headList都没有东西了,整个大Node要删掉,要更新大headList 76 * 又因为加入了新节点,所以又要更新headList 77 * 先删再加 78 */ 79 if headList != nil 80 { 81 modifyHeadList(headList!) 82 } 83 //不要忘记在kNMap中删掉 84 kNMap[deNode.key] = nil 85 heads[deNode] = nil 86 size -= 1 87 } 88 } 89 //新建 次数为1 90 let node = Node(key, val, 1) 91 92 //整个大链表都不存在 93 if headList == nil 94 { 95 //建出大链表的头部 96 headList = NodeList(node) 97 } 98 else 99 { 100 // 已经有了大链表的头部 101 /** 102 * 如果有 次数为1的头 就直接添加到大头的头部 103 * 如果没有次数为1大头 就建一个大头 然后添加到大头的尾部 104 */ 105 //大链表的头的头 的次数是 1 也就是说 有为times的小链表 106 if headList?.head?.times == 1 107 { 108 //加到这里 109 headList?.addNodeFromHead(node) 110 } 111 else 112 { 113 //没有times为 1 的小链表 要自己建一个 114 //建出一个times为1的小链表 115 let newList = NodeList(node) 116 newList.next = headList 117 headList?.pre = newList 118 headList = newList 119 } 120 } 121 //最后再添加这条记录 122 kNMap[key] = node 123 heads[node] = headList 124 size += 1 125 } 126 } 127 128 /** 129 * 解耦原来的链表 并放入到一个新的链表中 130 * 131 * @param node 这个node 132 * @param oldNodeList node 的原来属于的list 133 */ 134 func move(_ node:Node?,_ oldNodeList:NodeList) 135 { 136 //老链表你自己先删掉 137 oldNodeList.deleteNode(node) 138 139 let preList = modifyHeadList(oldNodeList) ? oldNodeList.pre : oldNodeList 140 //要去的地方 141 let nextList = oldNodeList.next 142 143 //你的oldNodeList是大链表的最后一个 144 if nextList == nil 145 { 146 //建一个 147 let newList = NodeList(node) 148 if preList != nil 149 { 150 preList?.next = newList 151 } 152 newList.pre = preList 153 if headList == nil 154 { 155 headList = newList 156 } 157 if node != nil 158 { 159 heads[node!] = newList 160 } 161 } 162 //不是最后一个不是times最高的 163 else 164 { 165 //下一个存在 就直接挂在下一个的头部 166 if nextList?.head?.times == node?.times 167 { 168 nextList?.addNodeFromHead(node) 169 if node != nil 170 { 171 heads[node!] = nextList 172 } 173 } 174 //下一个不是 times + 1的 要自己新建一个node 然后左右两边重新连接好 175 else 176 { 177 let newList = NodeList(node) 178 179 if preList != nil 180 { 181 preList?.next = newList 182 } 183 newList.pre = preList 184 newList.next = nextList 185 nextList?.pre = newList 186 //这个是也要更换头 187 if headList == nextList 188 { 189 headList = newList 190 } 191 if node != nil 192 { 193 heads[node!] = newList 194 } 195 } 196 } 197 } 198 199 /** 200 * 这个方法的调用时机是 把一个node从一个nodelist中删掉 ,然后判断是不是要不这个nodelist给删掉 201 * 就是在delete之后, 要不要把整个小链表删掉 202 * 203 * @param nodeList 204 */ 205 func modifyHeadList(_ nodeList:NodeList) -> Bool 206 { 207 //为空了才要删掉整个大链表中的这个结点 208 if nodeList.isEmpty() 209 { 210 //要删的这个 是整个大链表的头部 211 if headList == nodeList 212 { 213 //新的头部是老头部的下一个 214 headList = headList?.next 215 if headList != nil 216 { 217 headList?.pre = nil 218 } 219 } 220 else 221 { 222 //要删的不是头 223 nodeList.pre?.next = nodeList.next 224 if nodeList.next != nil 225 { 226 nodeList.next?.pre = nodeList.pre 227 } 228 } 229 //也就是 这个是要整个都要删掉的 230 return true 231 } 232 //不空的话(也就是不只一个)就不要删 留着 233 return false 234 } 235 } 236 //小链表(挂在下面的) 237 class Node:Hashable 238 { 239 static func == (lhs: Node, rhs: Node) -> Bool { 240 return lhs.key == rhs.key 241 } 242 243 func hash(into hasher: inout Hasher) 244 { 245 hasher.combine(key) 246 } 247 //map中push的key 248 var key:Int 249 //map中对应的value 250 var val:Int 251 //操作的次数 252 var times:Int 253 //小链表的上一个 254 var up:Node? 255 //小链表的下一个 256 var down:Node? 257 258 init(_ key:Int,_ val:Int,_ times:Int) 259 { 260 self.key = key 261 self.val = val 262 self.times = times 263 } 264 } 265 266 //大的链表的结点结构 (每一个结点都是一个小链表) 267 class NodeList:Hashable 268 { 269 static func == (lhs: NodeList, rhs: NodeList) -> Bool { 270 return lhs.head == rhs.head && lhs.tail == rhs.tail 271 } 272 273 func hash(into hasher: inout Hasher) 274 { 275 hasher.combine(head) 276 hasher.combine(tail) 277 } 278 279 //大链表的头部指针 280 var head:Node? 281 //大链表的尾部指针 282 var tail:Node? 283 //大链表的前一个结点 284 var pre:NodeList? 285 //大链表的下一个结点 286 var next:NodeList? 287 288 init(_ node:Node?) 289 { 290 self.head = node 291 self.tail = node 292 } 293 294 //返回这个小链表(小链表本身又是大链表的结点)是不是空的 295 func isEmpty() -> Bool 296 { 297 return head == nil 298 } 299 300 //小链表的头部添加结点 301 func addNodeFromHead(_ newHead:Node?) 302 { 303 newHead?.down = head 304 head?.up = newHead 305 head = newHead 306 } 307 308 //删除小链表中的任意一个结点 309 func deleteNode(_ node:Node?) 310 { 311 //只有一个结点 312 if head == tail 313 { 314 head = nil 315 tail = nil 316 } 317 else 318 { 319 //删除的是小链表的头部 320 if head == node 321 { 322 //头结点变成下一个 323 head = head?.down 324 //头结点的上一个 置空 325 head?.up = nil 326 } 327 //删除的是小链表的尾部 328 else if tail == node 329 { 330 tail = tail?.up 331 tail?.down = nil 332 } 333 //删除的是链表的中间 334 else 335 { 336 node?.up?.down = node?.down 337 node?.down?.up = node?.up 338 } 339 } 340 //完全断链 341 node?.up = nil 342 node?.down = nil 343 } 344 } 345 /** 346 * Your LFUCache object will be instantiated and called as such: 347 * let obj = LFUCache(capacity) 348 * let ret_1: Int = obj.get(key) 349 * obj.put(key, value) 350 */
424ms
1 class LFUCache { 2 3 var capacity: Int 4 var count: Int 5 var min: Int 6 var nodeMap: [Int: DLNode] 7 var countMap: [Int: DLList] 8 init(_ capacity: Int) { 9 self.capacity = capacity 10 self.count = 0 11 self.min = Int.max 12 self.nodeMap = [Int: DLNode]() 13 self.countMap = [Int: DLList]() 14 } 15 16 func get(_ key: Int) -> Int { 17 if let node = nodeMap[key] { 18 updateNode(node) 19 return node.value 20 } 21 else { 22 return -1 23 } 24 } 25 26 func put(_ key: Int, _ value: Int) { 27 guard capacity > 0 else { return } 28 if let node = nodeMap[key] { 29 node.value = value 30 updateNode(node) 31 } else { 32 if count == capacity { 33 if let minList = countMap[min] { 34 let removed = minList.removeLast() 35 nodeMap[removed.key] = nil 36 count -= 1 37 } 38 } 39 let node = DLNode(key, value) 40 nodeMap[key] = node 41 if let firstList = countMap[1] { 42 firstList.add(node) 43 } else { 44 countMap[1] = DLList(node) 45 } 46 count += 1 47 min = 1 48 } 49 } 50 private func updateNode(_ node: DLNode) { 51 if let list = countMap[node.count] { 52 list.remove(node) 53 if node.count == min, list.isEmpty { 54 min += 1 55 } 56 node.count += 1 57 if let newList = countMap[node.count] { 58 newList.add(node) 59 } else { 60 countMap[node.count] = DLList(node) 61 } 62 } 63 } 64 65 } 66 67 68 69 70 class DLNode { 71 var key: Int 72 var value: Int 73 var count: Int 74 var pre: DLNode? 75 var next: DLNode? 76 init(_ key: Int, _ value: Int) { 77 self.key = key 78 self.value = value 79 count = 1 80 } 81 } 82 83 class DLList { 84 var head: DLNode 85 var tail: DLNode 86 var isEmpty: Bool { 87 return head.next === tail && tail.pre === head 88 } 89 init(_ node: DLNode) { 90 head = DLNode(0, 0) 91 tail = DLNode(0, 0) 92 head.next = node 93 node.pre = head 94 node.next = tail 95 tail.pre = node 96 97 } 98 func add(_ node: DLNode) { 99 node.pre = head 100 node.next = head.next 101 node.next?.pre = node 102 head.next = node 103 } 104 func remove(_ node: DLNode) { 105 node.pre?.next = node.next 106 node.next?.pre = node.pre 107 } 108 func removeLast() -> DLNode { 109 let node = tail.pre! 110 remove(node) 111 return node 112 } 113 } 114 115 /** 116 * Your LFUCache object will be instantiated and called as such: 117 * let obj = LFUCache(capacity) 118 * let ret_1: Int = obj.get(key) 119 * obj.put(key, value) 120 */
448ms
1 class LFUCache { 2 3 private let capacity: Int 4 private var nodeMap = [Int: CacheNode]() 5 private var listMap = [Int: CacheList]() 6 private var size = 0 7 private var leastFrequency = 1 8 9 init(_ capacity: Int) { 10 self.capacity = capacity 11 } 12 13 func get(_ key: Int) -> Int { 14 guard let node = nodeMap[key], let list = listMap[node.count] else { 15 return -1 16 } 17 updateExsit(node: node) 18 return node.val 19 } 20 21 func put(_ key: Int, _ value: Int) { 22 if capacity == 0 { 23 return 24 } 25 26 if let node = nodeMap[key], let list = listMap[node.count] { 27 node.val = value 28 updateExsit(node: node) 29 } else { 30 removeCacheIfNeeded() 31 32 let node = CacheNode(key, value) 33 nodeMap[key] = node 34 listMap(add: node) 35 36 size += 1 37 leastFrequency = 1 38 } 39 } 40 41 private func updateExsit(node: CacheNode) { 42 guard let list = listMap[node.count] else { 43 return 44 } 45 list.remove(node) 46 47 if list.isEmpty { 48 listMap[node.count] = nil 49 50 if leastFrequency == node.count { 51 leastFrequency += 1 52 } 53 } 54 55 node.count += 1 56 listMap(add: node) 57 } 58 59 private func removeCacheIfNeeded() { 60 guard size >= capacity, let list = listMap[leastFrequency], let key = list.removeLast()?.key else { 61 return 62 } 63 size -= 1 64 nodeMap[key] = nil 65 if list.isEmpty { 66 listMap[leastFrequency] = nil 67 } 68 } 69 70 private func listMap(add node: CacheNode) { 71 let list = listMap[node.count, default: CacheList()] 72 list.add(node) 73 listMap[node.count] = list 74 } 75 76 } 77 78 class CacheList { 79 80 private let head = CacheNode(0, 0) 81 private let tail = CacheNode(0, 0) 82 private var count = 0 83 84 var isEmpty: Bool { 85 return count <= 0 86 } 87 88 init() { 89 head.next = tail 90 tail.pre = head 91 } 92 93 func add(_ node: CacheNode) { 94 head.next?.pre = node 95 node.next = head.next 96 node.pre = head 97 head.next = node 98 count += 1 99 } 100 101 102 func remove(_ node: CacheNode) { 103 node.pre?.next = node.next 104 node.next?.pre = node.pre 105 node.next = nil 106 node.pre = nil 107 count -= 1 108 } 109 110 func removeLast() -> CacheNode? { 111 guard !isEmpty, let node = tail.pre else { 112 return nil 113 } 114 remove(node) 115 return node 116 } 117 118 } 119 120 class CacheNode { 121 let key: Int 122 var val: Int 123 var pre: CacheNode? 124 var next: CacheNode? 125 var count = 1 126 127 init(_ key: Int, _ val: Int) { 128 self.key = key 129 self.val = val 130 } 131 } 132 133 /** 134 * Your LFUCache object will be instantiated and called as such: 135 * let obj = LFUCache(capacity) 136 * let ret_1: Int = obj.get(key) 137 * obj.put(key, value) 138 */
500ms
1 class Node: CustomStringConvertible { 2 var key: Int 3 var val: Int 4 var next: Node? 5 var prev: Node? 6 init(_ key: Int, _ val: Int) { 7 self.key = key 8 self.val = val 9 } 10 var description: String { 11 return "(\(val))" 12 } 13 } 14 15 class FreqNode: CustomStringConvertible { 16 var freq: Int 17 var next: FreqNode? 18 var prev: FreqNode? 19 var head = Node(-1, -1) 20 var tail = Node(-1, -1) 21 var nodeMap = [Int: Node]() // key to node 22 var count: Int { 23 return nodeMap.count 24 } 25 init(_ freq: Int) { 26 self.freq = freq 27 head.next = tail 28 tail.prev = head 29 } 30 var description: String { 31 var str = "f:\(freq) [" 32 var c = nodeMap.count 33 for (key, val) in nodeMap { 34 str += "\(key):\(val.key)" 35 c -= 1 36 if c != 0 { 37 str += "," 38 } 39 } 40 str += "] " 41 var node: Node? = head 42 while let n = node { 43 if n !== head, n !== tail { 44 let ptr = n.next === tail ? "" : "->" 45 str += "\(n)\(ptr)" 46 } 47 node = n.next 48 } 49 return "{ " + str + " }" 50 } 51 } 52 53 class LFUCache: CustomStringConvertible { 54 private var capacity: Int 55 private var head = FreqNode(-1) 56 private var tail = FreqNode(-1) 57 private var freqMap = [Int: FreqNode]() // key to freq node 58 private var count: Int = 0 59 var description: String { 60 var str = "c:\(count), [" 61 var c = freqMap.count 62 for (key, val) in freqMap { 63 str += "\(key):\(val.freq)" 64 c -= 1 65 if c != 0 { 66 str += "," 67 } 68 } 69 str += "] " 70 var fNode: FreqNode? = head 71 while let f = fNode { 72 if f !== head, f !== tail { 73 let ptr = f.next === tail ? "" : " --> " 74 str += "\(f)\(ptr)" 75 } 76 fNode = f.next 77 } 78 return str 79 } 80 81 init(_ capacity: Int) { 82 self.capacity = capacity 83 head.next = tail 84 tail.prev = head 85 } 86 87 func get(_ key: Int) -> Int { 88 if capacity <= 0 { return -1 } 89 guard let freqNode = freqMap[key], 90 let node = freqNode.nodeMap[key] else { 91 return -1 92 } 93 access(key, freqNode, node, false) 94 return node.val 95 } 96 97 func put(_ key: Int, _ value: Int) { 98 if capacity <= 0 { return } 99 let isNew = freqMap[key] == nil || freqMap[key]?.nodeMap[key] == nil 100 let freqNode = freqMap[key] 101 let node = freqNode?.nodeMap[key] ?? Node(key, value) 102 node.key = key 103 node.val = value 104 access(key, freqNode, node, isNew) 105 } 106 107 private func access(_ key: Int, _ freqNode: FreqNode?, _ node: Node, _ isNew: Bool) { 108 if isNew { 109 count += 1 110 } 111 if count > capacity { 112 if tail.prev?.count == 1 { // remove the entire freq node 113 if let key = tail.prev?.nodeMap.keys.first { 114 freqMap[key] = nil 115 // print("=======1. evicting \(key)") 116 } 117 tail.prev?.prev?.next = tail 118 tail.prev = tail.prev?.prev 119 } else { // remove node only 120 let t = tail.prev?.tail 121 let last = tail.prev?.tail.prev 122 if let key = last?.key { 123 tail.prev?.nodeMap[key] = nil 124 freqMap[key] = nil 125 // print("=======2. evicting \(key)") 126 } 127 last?.prev?.next = t 128 t?.prev = last?.prev 129 } 130 count -= 1 131 } 132 133 let newFreq = (freqNode?.freq ?? 0) + 1 134 var newFreqNode: FreqNode 135 if let freqNode = freqNode, 136 freqNode.count == 1, 137 freqNode.prev?.freq != newFreq { // use current node 138 freqNode.freq = newFreq 139 newFreqNode = freqNode 140 } else { 141 if let prev = freqNode?.prev, 142 prev.freq == newFreq { // use prev node 143 newFreqNode = prev 144 } else { // create new node 145 if let freqNode = freqNode { // insert the new node before 146 newFreqNode = FreqNode(newFreq) 147 newFreqNode.prev = freqNode.prev 148 newFreqNode.next = freqNode 149 freqNode.prev?.next = newFreqNode 150 freqNode.prev = newFreqNode 151 } else if let last = tail.prev, last.freq == 1 { // use tail 152 newFreqNode = last 153 } else { // append to tail 154 newFreqNode = FreqNode(1) 155 newFreqNode.prev = tail.prev 156 newFreqNode.next = tail 157 tail.prev?.next = newFreqNode 158 tail.prev = newFreqNode 159 } 160 } 161 // remove node from old freq node 162 freqNode?.nodeMap[key] = nil 163 node.prev?.next = node.next 164 node.next?.prev = node.prev 165 node.next = nil 166 node.prev = nil 167 if freqNode?.count == 0 { 168 freqNode?.prev?.next = freqNode?.next 169 freqNode?.next?.prev = freqNode?.prev 170 freqMap[key] = nil 171 } 172 } 173 // update node order in new freq node 174 freqMap[key] = newFreqNode 175 if newFreqNode.nodeMap[key] == nil { 176 node.next = newFreqNode.head.next 177 node.prev = newFreqNode.head 178 newFreqNode.head.next?.prev = node 179 newFreqNode.head.next = node 180 } 181 newFreqNode.nodeMap[key] = node 182 } 183 }
512ms
1 class LFUCache { 2 var cap: Int 3 var map : [Int: Node] // key, node 4 var fmap : [Int: NodeList] // count , list 5 // var max : Int 6 var min : Int 7 init(_ capacity: Int) { 8 cap = capacity 9 map = [Int: Node]() 10 fmap = [Int: NodeList]() 11 min = 0 12 } 13 14 func get(_ key: Int) -> Int { 15 // print("get \(key)") 16 if let node = map[key]{ 17 let list = fmap[node.count]! 18 list.removeNode(node) 19 if list.isEmpty() && min == node.count{ 20 fmap[node.count] = nil 21 min += 1 22 } 23 node.count += 1 24 if let nextList = fmap[node.count]{ 25 nextList.addFirst(node) 26 }else{ 27 let nextList = NodeList() 28 nextList.addFirst(node) 29 fmap[node.count] = nextList 30 } 31 return node.val 32 }else{ 33 return -1 34 } 35 } 36 37 func put(_ key: Int, _ value: Int) { 38 // print("put\(key)") 39 guard cap > 0 else { return } 40 if let node = map[key]{ 41 let list = fmap[node.count]! 42 list.removeNode(node) 43 if list.isEmpty() && min == node.count{ 44 fmap[node.count] = nil 45 min += 1 46 } 47 node.count += 1 48 node.val = value 49 if let nextList = fmap[node.count]{ 50 nextList.addFirst(node) 51 }else{ 52 let nextList = NodeList() 53 nextList.addFirst(node) 54 fmap[node.count] = nextList 55 } 56 }else{ 57 if map.keys.count == cap{ 58 if let list = fmap[min]{ 59 let last = list.removeLast() 60 if list.isEmpty() { 61 fmap[min] = nil 62 } 63 map[last.key] = nil 64 } 65 } 66 var newNode = Node(value,key) 67 map[key] = newNode 68 if let nextList = fmap[1]{ 69 nextList.addFirst(newNode) 70 }else{ 71 let nextList = NodeList() 72 nextList.addFirst(newNode) 73 fmap[1] = nextList 74 } 75 min = 1 76 } 77 } 78 } 79 80 class Node{ 81 var next : Node? = nil 82 var pre : Node? = nil 83 var val : Int 84 var key: Int 85 var count = 1 86 87 init(_ value : Int, _ key: Int){ 88 self.val = value 89 self.key = key 90 } 91 } 92 93 class NodeList{ 94 var head = Node(0,0) 95 var tail = Node(0,0) 96 97 init() { 98 head.next = tail 99 tail.pre = head 100 } 101 102 func addFirst(_ node: Node){ 103 let curr = head.next! 104 head.next = node 105 node.next = curr 106 curr.pre = node 107 node.pre = head 108 } 109 110 func removeNode(_ node: Node){ 111 let pre = node.pre! 112 let next = node.next! 113 next.pre = pre 114 pre.next = next 115 } 116 117 func removeLast()-> Node{ 118 let last = tail.pre! 119 removeNode(last) 120 return last 121 } 122 123 func isEmpty() -> Bool { 124 if head.next === tail { 125 return true 126 } 127 return false 128 } 129 } 130 131 /** 132 * Your LFUCache object will be instantiated and called as such: 133 * let obj = LFUCache(capacity) 134 * let ret_1: Int = obj.get(key) 135 * obj.put(key, value) 136 */