2020-09-18:LRU手擼,說下時間複雜度和空間複雜度。

福哥答案2020-09-18:node

方法:哈希表 + 雙向鏈表。
時間複雜度:對於 put 和 get 都是 O(1)。
空間複雜度:O(capacity),由於哈希表和雙向鏈表最多存儲 capacity+1 個元素。緩存

代碼用go語言編寫,代碼以下:spa

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
}

執行結果以下:
在這裏插入圖片描述code


評論blog

相關文章
相關標籤/搜索