zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    Input 银行卡验证
    记一次坑爹的加解密问题
    C# Html Agility Pack
    记一次坑爹的 “跨域” 问题
    FindControl的使用方法
    C#如何使用异步编程
    ReportViewer中设置ServerReport.ReportServerCredentials属性的方法
    C#中常用接口介绍
    谈谈C#中的接口
    DataTable与Linq相互转换
  • 原文地址:https://www.cnblogs.com/sherylwang/p/5578806.html
Copyright © 2011-2022 走看看