您的位置:首页 > 其它

Leetcode 146. LRU Cache

2018-02-07 21:57 417 查看

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) &
9611
lt;< endl;       // returns -1 (not found)
cout << cache.get(3) << endl;      // returns 3
cout << cache.get(4) << endl;       // returns 4
}


这道题的难点就在于概念不清楚,需要查资料。对于没有接触过的人来说,可以确实配得上leetcode的hard难度。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: