[Leetcode] LRU Cache

Source: Internet
Author: User

Title: LRU Cache

In the operating system, there are LRU algorithms in the page replacement algorithm (the most recent unused algorithm), the algorithm principle is as follows:

When each page is paged into memory, there is a time interval to record the current page distance from the most recent visit.

When each visit to the page, if the page is already in memory, the page corresponding to the time flag is emptied, the other flags plus one;

If the page replacement algorithm is called when the current page is not in memory and there is no idle size in memory, all pages are looked up and the largest page in the flag above is found and the memory is paged out.

If the memory can hold 4 pages, and the following procedure calls the page, its replacement process is as follows:

Order of call Pages: 4,7,0,7,1,0,1,2,1,2,6

4

7 4

0 7 4

7 0 4

1 7 0 4

0 1 7 4

1 0 7 4

2 1 0 7

1 2 0 7

2 1 0 7

6 2 1 0

The above page from left to right to become inactive, each time to replace, the first to displace the rightmost page;

The topic is to use the LRU algorithm to design a cache, the process is the same as above.

Requirements: Each method access is the time complexity of O (1);

When the LRU algorithm accesses the time complexity of O (1) while updating the cache block, it is necessary to insert and delete the hash table and the linked list, but how to use it together is a problem.

The hash table must need key, but what is the corresponding value to save? At the beginning, I put the value directly into the list, but so the list and unordered_map corresponding to the only in the Unordered_map to save the list of iterators;

I thought it would be possible, but when I was ready to do it, it suddenly occurred to me that inserting and deleting would invalidate the iterator behind it, so that the iterator could not be saved.

This is considered to be unable to allow the list to save value, because there is no way to bypass the problem of the iterator, so consider the list to save key, so unordered_map must save value, so I put unordered_map design so unordered_ Map<int, Pair<int, list<int>::iterator>> Mcahche;

The outermost int is the type of key, which has Pair<int, List<int>::iterator>, where first is Value,second is the iterator that corresponds to the list A list is required to achieve a sort of activity.

Then there is the following implementation:

/**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 ('ll always be positive) of the key if T He key exists in the cache, otherwise return-1.put (key, value)-Set or insert the value if the key is not already presen T. When the cache reached its capacity, it should invalidate the least recently used item before inserting a new item. Follow up:could do both operations in O (1) time complexity? Example:lrucache cache = new LRUCache (2);       2 is 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*/classLRUCache { Public: LRUCache (intcapacity): capacity (capacity) {}int Get(intkey); voidPutintKeyintvalue);Private:    intcapacity; List<int> Cache;//need quick Insert Delete, save key//because the list is deleted after the iterator will be invalidated, so that the subsequent use of the iterator to access the corresponding value is undefined behaviorunordered_map<int, pair<int, list<int>::iterator>> Mcahche;//need to quickly find O (1), save key with value and the corresponding iterator for key in cache};intLRUCache::Get(intkey) {Auto It= Mcahche.find (key);//Quick Find with unordered_map    if(It = = Mcahche.end ())return-1;//not found    intValue = it->second.first;//Save ValueCache.erase (It->second.second);//Delete the current node, It.second.second and the iterator behind it will be invalidatedCache.push_front (key);//insert it into the cache headerIt->second.second = Cache.begin ();//Assign the new iterator to the It.second.second    returnvalue;}voidLRUCache::p ut (intKeyintvalue) {Auto It= Mcahche.find (key);//Quick Find with unordered_map    if(It = = Mcahche.end ()) {//not found        if(cache.size () = = capacity) {//capacity is fullMcahche.erase (Cache.back ());//first delete the key-value pairs in the mapCache.pop_back ();//then delete the keys in the list} cache.push_front (key);//add a new key to the list firstMcahche[key] = {value, Cache.begin ()};//and add a new key-value pair to the map .    }    Else{It->second.first = value;//possible value is different, update valueCache.erase (It->second.second);//Delete the current node, It.second.second and the iterator behind it will be invalidatedCache.push_front (key);//insert it into the cache headerIt->second.second = Cache.begin ();//Assign the new iterator to the It.second.second    }}

Ideas:

In fact, this problem can not use a list, so that directly with the pointer will not have the problem of the iterator failure; you define a circular doubly linked list to replace the list, bidirectional is to facilitate unordered_map storage when it is not necessary to save its parent node (easy to delete), the loop is convenient to find the tail node ; You can directly use the circular single linked list to indicate that there is no problem;

Also note that the linked list is important to save key and value, why should there be a key? Because of the substitution, you also need to delete the corresponding items of unordered_map, which need to be found by key.

structDoublelistnode {//doubly linked listpair<int,int>Val; Doublelistnode*Front; Doublelistnode*Back ; Doublelistnode (intKeyintvalue): Val (Key,value), front (null), Back (null) {}};classLrucachebydoublelinklist { Public: Lrucachebydoublelinklist (intcapacity): Capacity (capacity), size (0), Cache (NULL) {}//do not forget the size and the initialization of the cache    int Get(intkey); voidPutintKeyintvalue);Private:    intcapacity;//Maximum Capacity    intSize//Cache Actual Length//Circular doubly linked list, easy to insert Delete, and find chain taildoublelistnode* Cache;//need quick Insert Delete, save valueunordered_map<int, Doublelistnode *> Mcahche;//need to quickly find O (1), save node for key and value};intLrucachebydoublelinklist::Get(intkey) {Auto It= Mcahche.find (key);//Quick Find with unordered_map    if(It = = Mcahche.end ())return-1;//not found    if(It->second = = cache)returncache->val.second;//if it's a chain head//Delete node of current linked listdoublelistnode* pre = it->second->Front; Pre->back = it->second->Back ; It->second->back->front =Pre; //inserts the current node to the top of the chainIt->second->back =Cache; It->second->front = cache->Front; Cache->front->back = it->second;//don't forget to update the forward pointer of the tail nodeCache->front = it->second; Cache= it->second; returnIt->second->Val.second;}voidLrucachebydoublelinklist::p ut (intKeyintvalue) {Auto It= Mcahche.find (key);//Quick Find with unordered_map    if(It = = Mcahche.end ()) {//not found        if(size = = capacity) {//capacity is fullcache = cache->front;//one step ahead of the head node.Mcahche.erase (Cache->val.first);//first delete the key-value pairs in the mapCache->val.first =key; Cache->val.second =value; Mcahche[key]= cache;//and add a new key-value pair to the map .            return; }        //capacity is not fulldoublelistnode* p =NewDoublelistnode (key, value); ++size; if(cache) {//linked list is not emptyP->back =Cache; P->front = cache->Front; Cache->front->back =p; Cache->front =p; Cache=p; Mcahche[key]= P;//and add a new key-value pair to the map .        }        Else{//The linked list is emptyP->back =p; P->front =p; Cache=p; Mcahche[key]= P;//and add a new key-value pair to the map .        }    }    Else{It->second->val.second = value;//possible value is different, update value        if(It->second = = cache)return;//if it's a chain head//Delete node of current linked listdoublelistnode* pre = it->second->Front; Pre->back = it->second->Back ; It->second->back->front =Pre; //inserts the current node to the top of the chainIt->second->back =Cache; It->second->front = cache->Front; Cache->front->back = it->second;//don't forget to update the forward pointer of the tail nodeCache->front = it->second; Cache= it->second; }}

[Leetcode] LRU Cache

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.