惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

M
MIT News - Artificial intelligence
罗磊的独立博客
Hugging Face - Blog
Hugging Face - Blog
J
Java Code Geeks
G
Google Developers Blog
美团技术团队
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
腾讯CDC
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
T
The Blog of Author Tim Ferriss
月光博客
月光博客
B
Blog
WordPress大学
WordPress大学
云风的 BLOG
云风的 BLOG
博客园_首页
人人都是产品经理
人人都是产品经理
aimingoo的专栏
aimingoo的专栏
Y
Y Combinator Blog
Jina AI
Jina AI
S
SegmentFault 最新的问题
H
Help Net Security
博客园 - 聂微东
Microsoft Azure Blog
Microsoft Azure Blog
Google DeepMind News
Google DeepMind News

博客园 - 来自海边的一片云

Binary Tree Maximum Path Sum 解题注意 CodingTMD’s Reading List De Bruijn 序列生成 Word Ladder I ,II 解题思路 suduko及8皇后问题及相关问题的解题思路 leetcode Word Break II 解题思路 Search for a string in an infinite stream of input string. 内存管理 Permutations leetcode Clone Graph leetcode 开弓没有回头箭 combination sum leetcode Combinations leetcode 组合问题 word break leetcode 重新试着写blog SQL injection Fuzz testing XML库的解析效率 Init()
LRU cache Leetcode
来自海边的一片云 · 2014-02-06 · via 博客园 - 来自海边的一片云

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. get,算是cache hit,首先要查找到这个node,然后再把这个node放到第一位

2. setval, 这个算是更新,如果找到,那么把他移到头上,如果找不到那就新建一个放到第一位。

因为涉及到元素的顺序,元素的更新,那么vector based的方案,统统不行。

最直接的实现是使用 double link list,然后查找就是线性查找,插入,删除O(1)但是当链表比较大时,查找就很慢。

需要查找快,那么就是hash或者map 这里最最合适的就是hash。

所以要搞出一个比较诡异的结构,

把双向链表放到一个以Key为哈希key的hash表中。

那么在查找的时候可以利用hash的O(1),快速的判断key是否在链表中。

当找到key之后,找到对应的链表结点,然后通过O(1)的复杂度,来更新链表。

另外一个trick是链表的操作中,使dumb node ,非常有助于简化问题。

因为是双向队列,所以使用两个dumb node。

class LRUCache{
public:
    struct LinkList
    {
        int val;
        int key;
        LinkList* next;
        LinkList* prev;
        LinkList(int k, int x) : key(k), val(x), next(NULL), prev(NULL){}
    };

    //link list operation to simplify operation introuduce 2 dummy node, head and tail
    LinkList *tail = NULL;
    LinkList *head = NULL;
    int gcapcity = 0;
    int size = 0;

    // due to performance hit, so put the key in the map or hastable, will
    // directly improve the performance of searching, actually,searching directly based on the map/hastable
    //
    unordered_map<int, LinkList*> nodeMap;

    LRUCache(int capacity) {
        gcapcity = capacity;
        tail = new LinkList(-1, -1);
        head = new LinkList(-1, -1);
        head->next = tail;
        tail->prev = head;
        size = 0;

    }

    void PutSingleNodetoHead(LinkList* node)
    {
        if (node == NULL) return;
        node->next = head->next;
        node->prev = head;
        head->next->prev = node;
        head->next = node;
    }

    int get(int key)
    {
        int val = -1;
        unordered_map<int, LinkList*>::iterator it = nodeMap.find(key);
        if (it != nodeMap.end()) //found
        {
            LinkList* node = it->second;
            val = node->val;
            node->prev->next = node->next;
            node->next->prev = node->prev;
            PutSingleNodetoHead(node);
        }

        return val;
    }

    void set(int key, int value) {
        unordered_map<int, LinkList*>::iterator it = nodeMap.find(key);
        if (it == nodeMap.end())
        {
            //not exist need insert one
            LinkList *node = new LinkList(key, value);
            PutSingleNodetoHead(node);
            nodeMap[key] = node;
            size++;

            if(size>gcapcity){  
                node = tail->prev;  
                tail->prev = node->prev;  
                node->prev->next = tail;  
                it = nodeMap.find(node->key);  
                nodeMap.erase(it);  
                delete node;  
            } 

        }
        else
        {
            LinkList* ptnode = it->second;
            ptnode->val = value;
            ptnode->prev->next = ptnode->next;
            ptnode->next->prev = ptnode->prev;
            PutSingleNodetoHead(ptnode);

        }

    }
};