zoukankan      html  css  js  c++  java
  • Leetcode: LRU Cache

    题目

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

    get(key) - Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1.
    set(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.

    思路

    1. 双向链表支持常数时间增删元素, 单向链表配合 hash table 也可以实现, 但是实现相当复杂

    2. hash table 存储链表中的元素

    总结

    1. 双向链表要处理的情况比单向链表更复杂

    2. 单向链表处理时, 仅需考虑 head 的问题, 但双向链表则需要考虑

      a) 增元素时, 考虑链表是否为空即 head 问题

      b) 删元素时, 要考虑被删除的元素是否为 head 

      c) LRU 操作, 前移元素时, 需要考虑被前移的元素是否为 Head, 这一个 bug 浪费了 2 个小时

      d) 有一个优化, 即 LRU set miss 时, 不需要显式的删除再增加节点, 仅需将 tail 节点的 key, value 修改 然后 head 前进一步即可

    代码

    class Node {
    public:
    	int key, value;
    	Node *next, *pre;
    	Node(int _key, int _value):key(_key), value(_value), next(NULL), pre(NULL){}
    };
    class LRUCache{
    public:
    	int capacity;
    	int curSize;
    	unordered_map<int, Node*> mp;
    	Node *head;
        LRUCache(int capacity) {
    		this->capacity = capacity;
    		curSize = 0;
        }
        
        int get(int key) {
          if(mp.find(key) == mp.end())
    		  return -1;
    	  int val = mp.find(key)->second->value;
    	  set(key, val);
    	  return val;
        }
        
        void set(int key, int value) {
    		int ans = 0;
    		if(mp.find(key) == mp.end())
    			ans = -1;
    		if(ans == -1) { // 新建一个 item
    			if(curSize >= capacity) { // 已满, 需要删除一个 item
    				if(capacity == 1) {
    					mp.erase(mp.find(head->key));
    					head->key = key;
    					head->value = value;
    					mp[key] = head;
    					return;
    				}else{	
    					// 模拟删除队尾元素
    					Node *tail = head->pre;
    					mp.erase(mp.find(tail->key));
    					tail->key = key;
    					tail->value = value;
    					head = tail;
    					mp[key] = head;
    					return;
    				}
    			}
    			// 未满, 添加元素
    			if(curSize == 0) {
    				head = new Node(key, value);
    				head->pre = head;
    				head->next = head;
    				mp[key] = head;
    				curSize++;
    				return ;
    			}else {
    				Node *al = new Node(key, value);
    				al->pre = head->pre;
    				al->next = head;
    				al->pre->next = al;
    				head->pre = al;
    				head = al;
    				mp[key] = al;
    				curSize++;
    				return;
    			}
    		}else{
    			if(head->key == key) {
    			    head->value = value;
    			    mp[key] = head;
    			    return;
    			}
    			//cout << "here" << endl;
    			Node *mid = mp.find(key)->second;
    			mid->next->pre = mid->pre;
    			mid->pre->next = mid->next;
    			mid->value = value;
    			mid->next = head;
    			mid->pre = head->pre;
    			head->pre = mid;
    			mid->pre->next = mid;
    			head = mid;
    			mp[key] = mid;	// 修改 mp[key]
    			return;
    		}
    	}
    };
    

      

    Update 

    #include <iostream>
    #include <map>
    using namespace std;
    
    class ListNode1 {
    public:
        ListNode1(int _key, int _val) {
            key = _key;
            val = _val;
            pre = next = NULL;
        }
    
        ListNode1 *pre;
        int key;
        int val;
        ListNode1 *next;
    };
    
    class LRUCache{
    public:
        LRUCache(int capacity) {
            this->capacity = capacity;
            head = NULL;
            size = 0;
        }
        
        int get(int key) {
            if(mp.count(key) == 0)
                return -1;
            int value = mp[key]->val;
            set(key, value);
            return value;
        }
        
        void set(int key, int value) {
            if(capacity == 1) {
                mp.clear();
                head = new ListNode1(key, value);
                mp[key] = head;
    
                return;
            }
            if(mp.count(key) > 0) {
                ListNode1 *curNode = mp[key];
                curNode->val = value;
                
                if(curNode == head)
                    return;
    
                curNode->pre->next = curNode->next;
                curNode->next->pre = curNode->pre;
    
                head->pre->next = curNode;
                curNode->pre = head->pre;
                curNode->next = head;
                head->pre = curNode;
                head = curNode;
                
                return;
            }
    
            if(size < capacity) {
                
                size ++;
                ListNode1 *newNode = new ListNode1(key, value);
                mp[key] = newNode;
                if(size == 1) {
                    newNode->pre = newNode;
                    newNode->next = newNode;
                    head = newNode;
                    return;
                }
                head->pre->next = newNode;
                newNode->pre = head->pre;
                newNode->next = head;
                head->pre = newNode;
                head = newNode;
                return;
            }
            // size >= capacity
            ListNode1 *tail = head->pre;
            mp.erase(mp.find(tail->key));
            mp[key] = tail;
            tail->key = key;
            tail->val = value;
            head = tail;
    
        }
    private:
        int capacity;
        int size;
        map<int, ListNode1*> mp;
        ListNode1 *head;
    };
  • 相关阅读:
    PLSQL_Oracle Trigger触发器的基本概念和用法
    PLSQL_Oracle Object所有数据库对象类型汇总和简解(概念)
    OAF_EO系列2
    OAF_EO系列1
    OAF_OAF Debug And Log调试和记录工具的详解(案例)
    OAF_OAF Exception Handling异常处理(概念)
    DBA_FND Load程式迁移工具介绍和应用(案例)
    Form_Form标准控件Folder开发解析(案列)
    BEvent_标准BusinessEvent用以监控供应商的修改(案例)
    PLSQL_Oracle Logon Trigger的建立
  • 原文地址:https://www.cnblogs.com/xinsheng/p/3514968.html
Copyright © 2011-2022 走看看