前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >2020-09-18:LRU手撸,说下时间复杂度和空间复杂度。

2020-09-18:LRU手撸,说下时间复杂度和空间复杂度。

原创
作者头像
福大大架构师每日一题
修改2020-09-21 09:54:31
9870
修改2020-09-21 09:54:31
举报

福哥答案2020-09-18:

方法:哈希表 + 双向链表。

时间复杂度:对于 put 和 get 都是 O(1)。

空间复杂度:O(capacity),因为哈希表和双向链表最多存储 capacity+1 个元素。

代码用go语言编写,代码如下:

package test40_lru

import (
    "fmt"
    "testing"
)

/*
哈希表 + 双向链表
时间复杂度:对于 put 和 get 都是 O(1)O(1)。
空间复杂度:O(capacity),因为哈希表和双向链表最多存储 capacity+1 个元素。
*/
//https://leetcode-cn.com/problems/lru-cache/solution/lruhuan-cun-ji-zhi-by-leetcode-solution/
//go test -v -test.run TestLru
func TestLru(t *testing.T) {
    cache := NewLRUCache(2)

    cache.Put(1, 1)
    cache.Put(2, 2)
    cache.Get(1)    // 返回  1
    cache.Put(3, 3) // 该操作会使得关键字 2 作废
    cache.Get(2)    // 返回 -1 (未找到)
    cache.Put(4, 4) // 该操作会使得关键字 1 作废
    cache.Get(1)    // 返回 -1 (未找到)
    cache.Get(3)    // 返回  3
    cache.Get(4)    // 返回  4

}

type LRUCache struct {
    size       int
    capacity   int
    cache      map[int]*DLinkedNode
    head, tail *DLinkedNode
}

type DLinkedNode struct {
    key, value int
    prev, next *DLinkedNode
}

func NewDLinkedNode(key, value int) *DLinkedNode {
    return &DLinkedNode{
        key:   key,
        value: value,
    }
}

func NewLRUCache(capacity int) LRUCache {
    l := LRUCache{
        cache:    map[int]*DLinkedNode{},
        head:     NewDLinkedNode(0, 0),
        tail:     NewDLinkedNode(0, 0),
        capacity: capacity,
    }
    l.head.next = l.tail
    l.tail.prev = l.head
    return l
}

//获取元素
func (f *LRUCache) Get(key int) int {
    //如果缓存里未找到元素
    if _, ok := f.cache[key]; !ok {
        fmt.Println(-1)
        return -1
    }

    //缓存里有元素
    node := f.cache[key]

    //如果 key 存在,先通过哈希表定位,再移到头部
    f.moveToHead(node)
    fmt.Println(node.value)
    return node.value
}

//放入元素
func (f *LRUCache) Put(key int, value int) {
    //如果缓存里没有元素
    if _, ok := f.cache[key]; !ok {
        node := NewDLinkedNode(key, value)
        f.cache[key] = node
        //放在头部
        f.addToHead(node)
        f.size++
        //如果元素个数大于容量,需要删除元素
        if f.size > f.capacity {
            //删除链表尾部
            removed := f.removeTail()
            //删除map中的key
            delete(f.cache, removed.key)
            f.size--
        }
    } else { //缓存里有元素
        //获取元素
        node := f.cache[key]
        //修改值
        node.value = value
        //移动到链表头
        f.moveToHead(node)
    }
}

//添加到头节点
func (f *LRUCache) addToHead(node *DLinkedNode) {
    node.prev = f.head
    node.next = f.head.next
    f.head.next.prev = node
    f.head.next = node
}

//删除节点
func (f *LRUCache) removeNode(node *DLinkedNode) {
    node.prev.next = node.next
    node.next.prev = node.prev
}

//移动到头节点
func (f *LRUCache) moveToHead(node *DLinkedNode) {
    f.removeNode(node)
    f.addToHead(node)
}

//删除尾部
func (f *LRUCache) removeTail() *DLinkedNode {
    node := f.tail.prev
    f.removeNode(node)
    return node
}

执行结果如下:

***

[评论](https://user.qzone.qq.com/3182319461/blog/1600382890)

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档