Leetcode 146. LRU Cache

Leetcode 146. LRU Cache

前言

今天电话面试,具体哪一家公司就不透露了。
面试官叫我实现一个Cache。
我个人感觉答得不好,一开始就跑偏了。
事后发现这是一道经典题,有多经典呢?
经典到我队友昨天也说他面试另一家公司也出了这道题,然而我理解错了他的意思,导致没细看。
经典到我一和学长说,考Cache,学长就知道是这道题。(学长还是强)
经典到一位网友说

遇到过,很正常; 没遇到,早晚会遇到。 (出处)

由于我一开始就跑偏了,数据结构选错了,现在想想,面试官很多提醒我的点都是这题的注意事项,然而当时并不知道。
挫折在所难免,关键是不能在同一个地方跌倒两次。

题目

题目连接
首先弄清楚LRU是什么?
参考连接
最久没有访问的内容作为替换对象。

总结一下:
这个Cache有一个容量,在构造函数中会给出。
然后往里面put,如果容量没有满,就直接put。
否则呢,就开始替换。
怎么替换呢?
最久没有访问的作为替换对象。
get函数,输入key
如果命中了,就返回value
否则就返回-1.
最好O(1)实现。

那我们先不考虑LRU。直接就是一个Cache。既然要O(1),就用unordered_map就好了。
可以写出出这段代码

    int get(int key) {
        if (mp.count(key)) {
            return mp[key];
        } else {
            return -1;
        }
    }

    void put(int key, int value) {
        mp[key] = value;
    }

然后实现LRU,最久没有访问的出去。
既然要O(1),所有全网的解法都是拿list来说实现的。

set(key, value)时
首先看key在不在map里面,如果在就放在最前面,修改就好了,也不需加到Cache里去了。
当cache没有满的时候,一次加到list最前面。
当cache满的时候,就把最后一个拿掉。

get(key)的时候,就把
把list里面key为这个元素给放到最前面。
这样都是O(1)的。
这样我们需要同时记录每个key在list中的位置,即迭代器。
把这些功能加进去,就会形成正确代码。
我们发现可以复用一个函数,就叫它hit吧。
完整代码(带测试)

#include <bits/stdc++.h>
using namespace std;
class LRUCache {
private:
    unordered_map<int, pair<int, list<int>::iterator> > mp;
    int capacity;
    int sz;
    list<int> li;
    void hit(int key)
    {
            auto it = mp[key].second;
            li.erase(it);
            li.push_front(key);
            mp[key].second = li.begin();
    }
public:
    LRUCache(int capacity) : capacity(capacity) {
        sz = 0;
    }
    int get(int key) {
        if (mp.count(key)) {
            hit(key);
            return mp[key].first;
        } else {
            return -1;
        }
    }
    void put(int key, int value) {
        if (mp.count(key)) {
            mp[key].first = value;
            hit(key);
            return;
        }
        if (sz == capacity) {
            mp.erase(li.back());
            li.pop_back();
        } else {
            sz++;
        }
        li.push_front(key);
        mp[key].first = value;
        mp[key].second = li.begin();
    }
};

/**
 * Your LRUCache object will be instantiated and called as such:
 * LRUCache obj = new LRUCache(capacity);
 * int param_1 = obj.get(key);
 * obj.put(key,value);
 */
int main()
{
    LRUCache cache = LRUCache(2);
    cache.put(1, 1);
    cache.put(2, 2);
    cout << cache.get(1) << endl;     // returns 1
    cache.put(3, 3);    // evicts key 2
    cout << cache.get(2) << endl;      // returns -1 (not found)
    cache.put(4, 4);    // evicts key 1
    cout << cache.get(1) << endl;       // returns -1 (not found)
    cout << cache.get(3) << endl;      // returns 3
    cout << cache.get(4) << endl;       // returns 4
}

这道题的难点就在于概念不清楚,需要查资料。对于没有接触过的人来说,可以确实配得上leetcode的hard难度。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值