109 lines
2.0 KiB
Go
109 lines
2.0 KiB
Go
package main
|
|
|
|
import "log"
|
|
|
|
//https://leetcode-cn.com/problems/lru-cache/
|
|
//数组形式实现(O(n)),另外可以用双向链表+哈希表实现(O(1))
|
|
type LRUCache struct {
|
|
capacity int
|
|
cache map[int]int
|
|
lru []int
|
|
head int
|
|
tail int
|
|
}
|
|
|
|
func Constructor(capacity int) LRUCache {
|
|
return LRUCache{
|
|
capacity: capacity,
|
|
cache: make(map[int]int),
|
|
lru: make([]int, capacity),
|
|
head: 0, tail: 0,
|
|
}
|
|
}
|
|
|
|
func (this *LRUCache) Get(key int) int {
|
|
v, ok := this.cache[key]
|
|
if ok {
|
|
this.FloatUp(key)
|
|
return v
|
|
}
|
|
return -1
|
|
}
|
|
|
|
func (this *LRUCache) Put(key int, value int) {
|
|
this.cache[key] = value
|
|
this.FloatUp(key)
|
|
}
|
|
|
|
func (this *LRUCache) FloatUp(key int) {
|
|
//查找位
|
|
for i := 0; true; i++ {
|
|
var pos = this.pos(i + this.tail)
|
|
if key == this.lru[pos] {
|
|
//提到第一位,前面的后移
|
|
for ; true; i++ {
|
|
var pos = this.pos(i + this.tail)
|
|
if pos == this.head {
|
|
//到头了,跳出
|
|
break
|
|
}
|
|
this.lru[pos] = this.lru[this.pos(pos+1)]
|
|
}
|
|
this.head = this.head - 1
|
|
if this.head == -1 {
|
|
this.head = this.capacity - 1
|
|
}
|
|
break
|
|
} else if pos == this.head {
|
|
//到头了,跳出
|
|
break
|
|
}
|
|
}
|
|
var tmp = this.lru[this.tail]
|
|
this.head = this.pos(this.head + 1)
|
|
this.lru[this.head] = key
|
|
//判断是否已满
|
|
if this.head == this.tail {
|
|
//满,删除最后一位
|
|
delete(this.cache, tmp)
|
|
this.tail = this.pos(this.tail + 1)
|
|
}
|
|
}
|
|
|
|
func (this *LRUCache) pos(pos int) int {
|
|
return pos % this.capacity
|
|
}
|
|
|
|
/**
|
|
* Your LRUCache object will be instantiated and called as such:
|
|
* obj := Constructor(capacity);
|
|
* param_1 := obj.Get(key);
|
|
* obj.Put(key,value);
|
|
*/
|
|
|
|
func main() {
|
|
cache := Constructor(3)
|
|
cache.Put(1, 1)
|
|
cache.Put(2, 2)
|
|
cache.Put(3, 3)
|
|
cache.Put(4, 4)
|
|
cache.Get(4)
|
|
cache.Get(3)
|
|
cache.Get(2)
|
|
cache.Get(1)
|
|
cache.Put(5, 5)
|
|
cache.Get(1)
|
|
cache.Get(2)
|
|
cache.Get(3)
|
|
cache.Get(4)
|
|
cache.Get(5)
|
|
}
|
|
|
|
func Equal(expected, actual int) {
|
|
if expected != actual {
|
|
log.Fatalln(expected, "!=", actual)
|
|
} else {
|
|
log.Println("OK")
|
|
}
|
|
}
|