LRU缓存机制&分割回文串
1 LRU缓存机制
Least Recently Used,最近最少使用法则,如果容器的容量为N,那么容器里面总是保存最近使用的N个数据
设计实现LRU缓存机制,支持put操作,get操作(不存在就返回-1),要求时间复杂度为O(1);
思考:首先由时间复杂度O(1),可以想到我们可能需要使用数组以及哈希表;然后我们需要根据数据的使用频率来调整数据,在适当的时候删掉最不经常用的数据,那么我们可能就需要一个支持双向的容器(deque、list);
我们可以通过取数据的同时,将数据移动到容器的头部,这样,使用频率最低的数据就自动排到了末尾;那么我们需要在数据的中间位置删除元素,而list可以在常数时间复杂度删除元素,因此我们选择list;
由于list的查找时间复杂度O(N),所以,我们可以使用一个哈希表来存储对应的key,这样就实现了常数复杂度查找元素;而value我们存储在list里面,所以哈希表里面我们可以存储对应的迭代器,通过迭代器来访问对应的value;
最开始的思路,有一点问题:put的时候,如果容器已满,无法删除末尾元素在哈希表里面的键值
class LRU{
public:
int N;
list<int> ls;
unordered_map<int ,list<int>::iterator> mp;
public:
LRU(int n):N(n){
};
//插入
void put(int key,int value){
if(ls.size()==N){
//删除最后一个节点
mp.erase();//无法通过ls.back()来让mp删除对应的key
ls.pop_back();
}
if(mp.count(key)){
//如果之前的key已经存在,就将其value替换为新的value
ls.erase(mp[key]);
}
auto node=make_pair(key,value);
ls.push_front(node);
mp[key]=ls.begin();
}
//删除
int get(int key){
if(!mp.count(key))
return -1;
int value=*mp[key];
ls.erase(mp[key]);
ls.push_front(value);
mp[key]=ls.begin();
return value;
}
};
解决的方法是,在list里面存储key,以及value;这样就可以通过list里面的元素,得到其对应的键值key,从而就可以在哈希表里面删除对应的key
完整代码
/* LRU(Least Recently Used)缓存机制:支持get put 操作,总是保存最经常用的几个数据 */
#include<iostream>
#include<list>
#include<unordered_map>
using namespace std;
class LRU{
public:
int N;
list<pair<int,int>> ls;
unordered_map<int ,list<pair<int,int>>::iterator> mp;
public:
LRU(int n):N(n){
};
void put(int key,int value){
if(ls.size()==N){
//删除最后一个节点
mp.erase(ls.back().first);
ls.pop_back();
}
if(mp.count(key)){
//如果之前的key已经存在,就将其value替换为新的value
ls.erase(mp[key]);
}
auto node=make_pair(key,value);
ls.push_front(node);
mp[key]=ls.begin();
}
int get(int key){
if(!mp.count(key))
return -1;
auto node=make_pair(key,(*mp[key]).second);
ls.erase(mp[key]);
ls.push_front(node);
mp[key]=ls.begin();
return node.second;
}
};
int main(){
LRU solu{
4};
solu.put(1,100);
solu.put(2,200);
solu.put(3,300);
cout<<solu.get(2)<<endl;
cout<<solu.get(20)<<endl;
return 0;
}
2 分割回文串
#include<iostream>
#include<string>
#include<vector>
using namespace std;
class Solu{
private:
vector<vector<string>> ans;
vector<string> str;
public:
//回溯
void dfs(string& s,int left){
if(left==s.length()){
ans.push_back(str);
return;
}
for(int i=left;i<s.length();++i){
string tmp=s.substr(left,i-left+1);
if(isPalinStr(tmp)){
str.push_back(tmp);
dfs(s,left+1);
str.pop_back();
}
}
}
//判断字符串是否回文
bool isPalinStr(string& s){
int i=0,j=s.length()-1;
while(i<=j){
if(s[i]!=s[j])
return false;
i++;
j--;
}
return true;
}
vector<vector<string>> ReturnPalindormString(string s){
//返回s里面可以切割出的所有回文字符串方案
dfs(s,0);
return ans;
};
};
int main(){
string s="aab";
Solu S;
vector<vector<string>>&& ans=S.ReturnPalindormString(s);
return 0;
}
原来,还可以使用动态规划,提前存储好子字符串是否是回文串!!
继续努力 ୧((〃•̀ꇴ•〃))૭⁺✧
刷题总结类 文章被收录于专栏
这里记录一些刷题时候的总结思考