编程题之设计LRU缓存结构

编程题之设计LRU缓存结构

题目描述:

设计LRU缓存结构,该结构在构造时确定大小,假设大小为K,并有如下两个功能:

  • set (key, value):将记录(key, value)插入该结构
  • get(key) :返回key对应的value值

[要求]

  1. set和get方法的时间复杂度为O(1)。
  2. 某个key的set或get操作一旦发生,认为这个key的记录成了最常使用的。
  3. 当缓存的大小超过K时,移除最不经常使用的记录,即set或get最久远的。

若opt=1,接下来两个整数下x,y,表示set(x,y)。
若opt=2,接下来一个整数x,表示get(x),若未出现过或已被移除,则返回-1。
对于每个操作2,输出一个答案。

输入:
[ [1,1,1] , [1,2,2] , [1,3,2] , [2,1] , [1,4,4] , [2,2] ], 3
返回值:
[ 1, -1]

思路:
哈希表 + 双向链表
C++ 用unordered_map<int, DLinkedNode*> cache表示哈希表。
python 用dict()函数生成字典表示哈希表。

C++代码

struct DLinkedNode {
    int key, value;
    DLinkedNode* prev;
    DLinkedNode* next;
    DLinkedNode(): key(0), value(0), prev(nullptr), next(nullptr){}
    DLinkedNode(int _key, int _value): key(_key), value(_value), prev(nullptr), next(nullptr){}
};
class Solution {
public:
    /**
     * lru design
     * @param operators int整型vector<vector<>> the ops
     * @param k int整型 the k
     * @return int整型vector
     */
    vector<int> LRU(vector<vector<int> >& operators, int k) {
        // write code here
        vector<int> result;
        cap = k;
        size = 0;
        head = new DLinkedNode();
        tail = new DLinkedNode();
        head->next = tail;
        tail->prev = head;
        result.reserve(operators.size());
        if(k!=0) {
            for(const vector<int>& opt:operators) {
                if(opt[0]==1) put(opt[1],opt[2]);
                else if(opt[0]==2) result.push_back(get(opt[1]));
            }
        }
        return result;
    }
    
   
    int get(int key){
        if(!cache.count(key)){
            return -1;
        }
        //如果key存在,先通过哈希表定位,再移到头部
        DLinkedNode* node = cache[key];
        moveToHead(node);
        return node->value;
    }
    void put(int key, int value){
        if(!cache.count(key)){
            //如果key不存在,创建一个新的节点
            DLinkedNode* node =  new DLinkedNode(key, value);
            //添加进哈希表
            cache[key] = node;
            //添加至双向链表的头部
            addToHead(node);
            ++size;
            if(size > cap){
                //如果超出容量,删除双向链表的尾部节点
                DLinkedNode* removed = removeTail();
                //删除哈希表中对应的项
                cache.erase(removed->key);
                delete removed;
                --size;
            }
        }
        else{
            //如果key存在,先通过哈希表定位,再修改value,并移到头部
            DLinkedNode* node = cache[key];
            node->value = value;
            moveToHead(node);
        }
    }
    
    void addToHead(DLinkedNode* node){
        node->prev = head;
        node->next = head->next;
        head->next->prev = node;
        head->next = node;
    }
    
    void removeNode(DLinkedNode* node){
        node->prev->next = node->next;
        node->next->prev = node->prev;
    }
    
    void moveToHead(DLinkedNode* node){
        removeNode(node);
        addToHead(node);
    }
    DLinkedNode* removeTail(){
        DLinkedNode* node = tail->prev;
        removeNode(node);
        return node;
    }
    
private:
    unordered_map<int, DLinkedNode*> cache;
    DLinkedNode* head;
    DLinkedNode* tail;
    int size;
    int cap;
};

python代码

#
# lru design
# @param operators int整型二维数组 the ops
# @param k int整型 the k
# @return int整型一维数组
#
class DLinkedNode:
    def __init__(self, key=0, value=0):
        self.key = key
        self.value = value
        self.prev = None
        self.next = None

class Solution:
    def __init__(self):
        #创建一个空字典
        self.cache = dict()
        #使用伪头部和伪尾部节点
        self.head = DLinkedNode()
        self.tail = DLinkedNode()
        self.head.next = self.tail
        self.tail.prev = self.head
        self.cap = 0
        self.size = 0
    
    def get(self, key):
        if key not in self.cache:
            return -1
        # 如果key存在,先通过哈希表定位,再移到头部
        node = self.cache[key]
        self.moveToHead(node)
        return node.value
        
    def put(self, key, value):
        if key not in self.cache:
            #如果key不存在,创建一个新的节点
            node = DLinkedNode(key, value)
            #添加进哈希表
            self.cache[key] = node
            #添加至双向链表的头部
            self.addToHead(node)
            self.size += 1
            if self.size > self.cap:
                #如果超出容量,删除双向链表的尾部节点
                removed = self.removeTail()
                #删除哈希表中对应的项
                self.cache.pop(removed.key)
                self.size -= 1
        else:
            #如果key存在,先通过哈希表定位,再修改value,并移到头部
            node = self.cache[key]
            node.value = value
            self.moveToHead(node)
            
    def addToHead(self, node):
        node.prev = self.head
        node.next = self.head.next
        self.head.next.prev = node
        self.head.next = node
        
    def removeNode(self, node):
        node.prev.next = node.next
        node.next.prev = node.prev
    
    def moveToHead(self, node):
        self.removeNode(node)
        self.addToHead(node)
    
    def removeTail(self):
        node = self.tail.prev
        self.removeNode(node)
        return node
    
    def LRU(self , operators , k ):
        # write code here
        self.cap = k
        res = []
        for x in operators:
            if x[0] == 1:
                self.put(x[1], x[2])
            elif x[0] == 2:
                res.append(self.get(x[1]))
        return res
        
        

python实现在牛客网上运行超时!!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值