LRU Cache

这是一道非常高频,非常经典的题目:

首先分析下题意:

Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations: get and set.

get(key) - Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1.
set(key, value) - Set or insert the value if the key is not already present. When the cache reached its capacity, it should invalidate the least recently used item before inserting a new item.

主要是两个功能,一个是get,当LRU cache中存在该键时,则返回元素,不存在则返回-1。同时因为LRU cache纪录的是最近访问的元素,所以在做了get操作后,该get的元素需要放到最后。

另一个功能是set, 如果该键不存在,则在最后插入该元素(如果达到容量上限,则删除最前端元素least recently used),如果存在则和get中类似,将该元素移动到最后。

快速的访问键值,很容易想起使用hashmap, 但是另外一点是需要移动位置来反映元素的访问顺序,这个在经典的dict中没有实现,当然一个神器是可以纪录插入字典顺序的collections.OrderedDict(). OrderedDict()本身是使用dict和doubly linked list来实现的,doubly linked list的优点是O(1)时间删除和插入元素,则可以O(1)时间实现移动元素到队尾的功能。代码如下:

class node(object):
        def __init__(self, key, value):
            self.key = key
            self.val = value
            self.pre = None
            self.next = None
            
class LRUCache:
    # @param capacity, an integer
    def __init__(self, capacity):
        self.head = None
        self.tail = None
        self.map = {}
        self.capacity = capacity
    #remove node     
    def removeNode(self, key):
        n = self.map[key]
        if n != self.head:
            n.pre.next = n.next
            n.next.pre = n.pre
        else:
            self.head = n.next
            if n.next:
               n.next.pre = None
        self.map.pop(key)
    # add node at the end of doubly linked list    
    def addEnd(self, key, value):
        n = node(key, value)
        n.pre = self.tail
        if self.tail:
            self.tail.next = n
        self.tail = n
        self.map[key] = n
        if not self.head: #in case the capacity is 1
            self.head = n
            
    def get(self, key):
        if key not in self.map:
            return -1
        else:
            value = self.map[key].val
            if self.map[key] != self.tail:
                self.removeNode(key)
                self.addEnd(key, value)
            return value    

    def set(self, key, value):
        if key in self.map:
            if self.map[key] != self.tail: 
                self.removeNode(key)
                self.addEnd(key, value)   
            else:
                self.tail.val = value   
                self.map[key] = self.tail
        else:
            if len(self.map) == self.capacity:
                self.removeNode(self.head.key)
            self.addEnd(key, value)
            

OrderedDict:

class LRUCache(object):

    def __init__(self, capacity):
        """
        :type capacity: int
        """
        self.map = collections.OrderedDict()   #dict inside
        self.capacity = capacity
        

    def get(self, key):
        """
        :rtype: int
        """
        if key not in self.map:
            return -1
        else:
           value = self.map[key]
           self.map.pop(key)
           self.map[key] = value
           return value
        

    def set(self, key, value):
        """
        :type key: int
        :type value: int
        :rtype: nothing
        """
        if key in self.map:
            self.map.pop(key)
            self.map[key] = value
        else:
            if self.capacity == len(self.map):
                self.map.popitem(last = False)
                self.map[key] = value
            else:
                self.map[key] = value
原文地址:https://www.cnblogs.com/sherylwang/p/5578806.html