页面置换算法LRU实现--leetcode O(1)时间复杂度

来源:互联网 发布:杀破狼js 编辑:程序博客网 时间:2024/05/22 04:34

转载
作者:鱼与海洋
出处:http://www.cnblogs.com/joannacode/p/5998949.html


leetcode题目地址

https://leetcode.com/problems/lru-cache/

题目描述

Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations: get and put.

get(key) - Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1.
put(key, value) - Set or insert the value if the key is not already present. When the cache reached its capacity, it should invalidate the least recently used item before inserting a new item.

Follow up:
Could you do both operations in O(1) time complexity?

Example:

LRUCache cache = new LRUCache( 2 /* capacity */ );cache.put(1, 1);cache.put(2, 2);cache.get(1);       // returns 1cache.put(3, 3);    // evicts key 2cache.get(2);       // returns -1 (not found)cache.put(4, 4);    // evicts key 1cache.get(1);       // returns -1 (not found)cache.get(3);       // returns 3cache.get(4);       // returns 4

Subscribe to see which companies asked this question.

ac代码

采用 双向链表 + map(效率还是不错的 map进一步可用成unordered_map)

  • 数据结构设计
    这里写图片描述

这里写图片描述

typedef struct node{    int key;    int val;    struct node* pre;    struct node* next;    node(int _key = -1, int _val = -1)    {        key = _key;        val = _val;        pre = NULL;        next = NULL;    }}DNode;class LRUCache{public:    LRUCache(int _capacity) {        capacity = _capacity;        size = 0;        head = new DNode();        tail = new DNode();        head->next = tail;        tail->pre = head;        mp.clear();    }    int get(int key) {        map<int,DNode*>::iterator it= mp.find(key);        if(it == mp.end())  //如果在Cache中不存在该key, 则返回-1        {            return -1;         }        else        {            DNode* t =  it->second;            // 把 t分离出来,然后将t插入到头部位置            t->pre->next = t->next;            t->next->pre = t->pre;            t->pre = head;            t->next = head->next;            head->next = t;            t->next->pre = t;            return t->val;        }      }    void put(int key, int value) {        map<int,DNode*>::iterator it= mp.find(key);        if(it == mp.end())  //如果在Cache中不存在该key, 则返回-1        {            if(size == capacity) //如果双向链表容量已满即缓存容量已满,则将最近不使用的节点即链表最后一个数据节点删除             {                // 删除最后一个                DNode *tmp = tail->pre;                tail->pre->pre->next = tail;                           tail->pre = tmp->pre;                mp.erase(tmp->key);                delete tmp;                size--;            }            //把新节点插入到head的后面 更新map            DNode *newNode = new DNode(key, value);            newNode->pre = head;            newNode->next = head->next;            head->next = newNode;            newNode->next->pre = newNode;            mp[key] = newNode;//在hashtable添加key对应的表项             size++;//链表节点数++         }else{ // 当前put的可以存在,需要更新value            DNode* t =  it->second;            // 把 t分离出来,然后将t插入到头部位置            t->pre->next = t->next;            t->next->pre = t->pre;            t->val = value; //**            t->pre = head;            t->next = head->next;            head->next = t;            t->next->pre = t;            return;        }    }private:    int capacity;    int size;    DNode* head;     DNode* tail;    map<int,DNode*> mp;};

ac2 (C++ list + map)

考虑到c++ list本身就是个 双向链表,可以直接采用list(效率会比较差,不过能ac)

这里写图片描述

class LRUCache{public:    LRUCache(int _capacity) {        capacity = _capacity;        size = 0;        cachelist.clear();        mp.clear();    }    int get(int key) {        map<int,pair<int,int>>::iterator it= mp.find(key);        if(it == mp.end())  //如果在Cache中不存在该key, 则返回-1        {            return -1;         }        else        {            pair<int,int> t = it->second;            pair<int,int> newPair(t.first, t.second);            cachelist.remove(t);            cachelist.push_front(newPair);            return newPair.second;        }      }    void put(int key, int value) {        map<int,pair<int,int>>::iterator it= mp.find(key);        if(it == mp.end())  //如果在Cache中不存在该key, 则返回-1        {            if(size == capacity) //如果双向链表容量已满即缓存容量已满,则将最近不使用的节点即链表最后一个数据节点删除             {                pair<int,int> tmp = cachelist.back();                cachelist.pop_back();                mp.erase(tmp.first);                size--;            }            pair<int,int> newPair(key,value);            cachelist.push_front(newPair);            mp[key] = newPair;            size++;//链表节点数++         }else{ // 当前put的可以存在,需要更新value            pair<int,int> t = it->second;            pair<int,int> newPair(key,value);            cachelist.remove(t);            cachelist.push_front(newPair);            mp[t.first] = newPair;            return;        }    }private:    int capacity;    int size;    list<pair<int,int>> cachelist;    map<int, pair<int,int>> mp;};

ac3

按照数据结构图的思想来写代码会容易很多

typedef struct node{    int key;    int val;    struct node* next;    struct node* pre;    node(int _key = -1, int _val = -1){        key = _key;        val = _val;        next = NULL;        pre = NULL;    }}Dnode;class LRUCache {public:    int size;    int cap;    Dnode* head;    Dnode* tail;    map<int, Dnode*> mp;    LRUCache(int capacity) {        size = 0;        cap =capacity;        head = new Dnode;        tail = new Dnode;        head->next = tail;        tail->pre = head;    }    int get(int key) {        if(mp.count(key) == 0)            return -1;        Dnode*  oldPos = mp[key];        int val = oldPos->val; //要返回的val        Dnode* oldpre = oldPos->pre;        oldPos->next->pre = oldpre;        oldpre->next = oldPos->next;        delete oldPos;        mp.erase(key);        Dnode* newPos = new Dnode(key,val);        head->next->pre = newPos;        newPos->next = head->next;        newPos->pre = head;        head->next = newPos;        mp[key] = newPos;        return val;    }    void put(int key, int value) {        if(cap <= 0)            return;        int storeVal = get(key);        if(storeVal != -1)        {            head->next->val = value;            mp[key]->val = value;            return;        }        if(size == cap)        {            Dnode* delNode = tail->pre;            int delKey = delNode->key;            Dnode* delpre = tail->pre->pre;            delpre->next = tail;            tail->pre= delpre;            delete delNode;            mp.erase(delKey);            size --;        }        Dnode* newPos = new Dnode(key,value);        head->next->pre = newPos;        newPos->next = head->next;        newPos->pre = head;        head->next = newPos;        mp[key] = newPos;        size ++;    }};

上面的代码,改进一下get方法(可以优化一点运行时间)

int get(int key) {    if(mp.count(key) == 0)        return -1;    Dnode*  oldPos = mp[key];    int val = oldPos->val; //要返回的val    Dnode* oldpre = oldPos->pre;    oldPos->next->pre = oldpre;    oldpre->next = oldPos->next;    //delete oldPos;    //mp.erase(key);    //Dnode* newPos = new Dnode(key,val);    Dnode* newPos = oldPos; //直接更新    head->next->pre = newPos;    newPos->next = head->next;    newPos->pre = head;    head->next = newPos;    mp[key] = newPos;// 直接更新    return val;}
0 0
原创粉丝点击