• [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

    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  */ 
  • 相关阅读:
    项目游戏开发日记 No.0x000002
    项目游戏开发日记 No.0x000001
    项目游戏开发日记 No.0x00000
    需求获取常见的方法是进行客户访谈,结合你的实践谈谈会遇到什么问题,你是怎么解决的?
    当下大部分互联网创业公司为什么都愿意采用增量模型来做开发?
    迷茫踌躇的2018,整装待发的2019
    阿里云轻量应用服务器 搭建配置详解
    JS常用数组方法及实例
    使用CSS隐藏HTML元素的四种常用方法
    标签种类及CSS引入方法
  • 原文地址:https://www.cnblogs.com/strengthen/p/10816306.html
Copyright © 2020-2023  润新知