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

 

posted @ 2014-01-11 14:28  SangS  阅读(498)  评论(0编辑  收藏  举报