一个list存数据,一个unordered_map存key和对应数据的引用。 这里最最最最最最最最最关键的一点就是List增删改元素是不会使迭代器无效的,只要知道这个,写出对应的数据结构和算法应该不会难。
下面的代码对于数据的pair做了移动处理,可能可以提升get太多情况下的效能。不过不太知道这会不会产生UB,还请大手子解答!
public:
/**
* lru design
* @param operators int整型vector<vector<>> the ops
* @param k int整型 the k
* @return int整型vector
*/
unordered_map<int,list<pair<int,int>>::iterator> is_present;
list<pair<int,int>> cache;
vector<int> LRU(vector<vector<int> >& operators, int k) {
vector<int> result;
pair<int,int> cur_elem;
for (const vector<int>& operation: operators){
switch (operation[0]){
case 1:{
// Remove the key first if already present
if (is_present.count(operation[1]) != 0)
{
cur_elem = move(*is_present[operation[1]]);
cache.erase(is_present[operation[1]]);
is_present.erase(operation[1]);
cur_elem.second = operation[2];
cache.push_back(move(cur_elem));
}
else
{
cache.push_back(pair<int,int>(operation[1], operation[2]));
}
// Insert the key to the cache and the map
pair<int,list<pair<int,int>>::iterator> new_elem = {operation[1], prev(cache.end())};
is_present.insert(new_elem);
// Exceed maximum capacity, remove oldest
if (is_present.size() > k)
{
is_present.erase(cache.front().first);
cache.pop_front();
}
break;
}
case 2:{
if (is_present.count(operation[1]) == 0)
{
result.push_back(-1);
}
else
{
cur_elem = move(*is_present[operation[1]]);
result.push_back(cur_elem.second);
cache.erase(is_present[operation[1]]);
is_present.erase(operation[1]);
cache.push_back(move(cur_elem));
pair<int,list<pair<int,int>>::iterator> new_elem = {operation[1], prev(cache.end())};
is_present.insert(new_elem);
}
break;
}
default:
break;
}
}
return result;
}
};