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

举报
福大大架构师每日一题 发表于 2020/09/18 21:26:32 2020/09/18
【摘要】 福哥答案2020-09-18:#福大大架构师每日一题#方法:哈希表 + 双向链表。时间复杂度:对于 put 和 get 都是 O(1)。空间复杂度:O(capacity),因为哈希表和双向链表最多存储 capacity+1 个元素。代码用go语言编写,代码如下:package test40_lruimport ( "fmt" "testing")/*哈希表 + 双向链表时间复杂度...

福哥答案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
}

执行结果如下:

image.png


【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。