为有牺牲多壮志,敢教日月换新天。

[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 
➤如果链接不是山青咏芝的博客园地址,则可能是爬取作者的文章。
➤原文已修改更新!强烈建议点击原文地址阅读!支持作者!支持原创!
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★

热烈欢迎,请直接点击!!!

进入博主App Store主页,下载使用各个作品!!!

注:博主将坚持每月上线一个新app!!!

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

Runtime: 516 ms
Memory Usage: 21.3 MB
  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  */ 

 

posted @ 2019-05-05 21:06  为敢技术  阅读(546)  评论(0编辑  收藏  举报