460.lfu-cache.go 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. type listNode struct {
  2. key int
  3. val int
  4. cnt int
  5. prev *listNode
  6. next *listNode
  7. }
  8. type linkedList struct {
  9. head *listNode
  10. tail *listNode
  11. }
  12. func newLinkedList() *linkedList {
  13. head, tail := &listNode{}, &listNode{}
  14. head.next = tail
  15. tail.prev = head
  16. li := &linkedList{head, tail}
  17. return li
  18. }
  19. func (li *linkedList) remove(node *listNode) {
  20. node.prev.next = node.next
  21. node.next.prev = node.prev
  22. }
  23. type LFUCache struct {
  24. capacity int
  25. size int
  26. min int
  27. cache map[int]*listNode
  28. freq map[int]*linkedList
  29. }
  30. func Constructor(capacity int) LFUCache {
  31. var lfu LFUCache
  32. lfu.capacity = capacity
  33. lfu.cache = make(map[int]*listNode)
  34. lfu.freq = make(map[int]*linkedList)
  35. return lfu
  36. }
  37. func (this *LFUCache) Get(key int) int {
  38. if node, ok := this.cache[key]; ok {
  39. this.touch(node)
  40. return node.val
  41. }
  42. return -1
  43. }
  44. func (this *LFUCache) Put(key int, value int) {
  45. if this.capacity == 0 {
  46. return
  47. } // Can not put new node.
  48. if node, ok := this.cache[key]; ok {
  49. this.touch(node)
  50. node.val = value
  51. return
  52. } // If the key already exists, touch it and update the value.
  53. if this.size == this.capacity {
  54. li := this.freq[this.min]
  55. delete(this.cache, li.tail.prev.key)
  56. li.remove(li.tail.prev)
  57. if li.head.next == li.tail {
  58. delete(this.freq, this.min)
  59. }
  60. this.size--
  61. } // If the cache is full, remove the last element in the least freq list.
  62. newNode := &listNode{key, value, 1, nil, nil}
  63. this.insert(newNode)
  64. this.cache[key] = newNode
  65. this.min = 1
  66. this.size++ // Then, insert new node.
  67. }
  68. func (this *LFUCache) insert(node *listNode) {
  69. li := this.freq[node.cnt]
  70. if li == nil {
  71. li = newLinkedList()
  72. this.freq[node.cnt] = li
  73. }
  74. node.next = li.head.next
  75. node.prev = li.head
  76. li.head.next = node
  77. node.next.prev = node
  78. }
  79. func (this *LFUCache) touch(node *listNode) {
  80. li := this.freq[node.cnt]
  81. li.remove(node)
  82. if li.head.next == li.tail {
  83. delete(this.freq, node.cnt)
  84. if node.cnt == this.min {
  85. this.min++
  86. }
  87. }
  88. node.cnt++
  89. this.insert(node)
  90. }
  91. /**
  92. * Your LFUCache object will be instantiated and called as such:
  93. * obj := Constructor(capacity);
  94. * param_1 := obj.Get(key);
  95. * obj.Put(key,value);
  96. */