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;
}

原来,还可以使用动态规划,提前存储好子字符串是否是回文串!!


继续努力 ୧((〃•̀ꇴ•〃))૭⁺✧