LeetCode刷题笔记——LRU算法

LeetCode刷题笔记——LRU算法

1. 什么是LRU算法?

LRU是一种缓存淘汰机制。

说到这里,我们顺便回顾一下常用的缓存算法都有哪些?

  • LRU 最近最久未使用 最近使用时间
  • LFU 最近最少使用 使用频率
  • FIFO 先进先出
    全称是Least Recently Used(最近最久未使用)

2.LRU算法数据结构是什么样子?

Leetcode上有一道LRU算法设计题目。让你设计数据结构,首先构造函数接收一个capacity参数作为缓存的最大容量,然后实现两个API:

  • put(key,val)插入新的或者更新已有的键值对。
  • get(key) 获取key对应的val,如果key不存在,返回-1.
    get和put的时间复杂度必须是O(1)

首先我们看一下缓存的数据结构有什么特点:

  • 需要实现根据key在O(1)时间找到value,很容易想到用hash表实现。
  • 需要保存结点的前后关系,有两种备选方法:数组,链表。
  • 需要在O(1)时间复杂度内插入删除结点。在给定一个结点情况下,要想实现从链表中删除这个结点,必须是双向链表。所以最终方案是hash表+双向链表。
  • node中需要哪些信息?
    • value必须的。
    • key?也是需要的。我们执行put操作且缓存满的情况下,我们需要找到链表中的最后一个结点,把它从链表中删除,同时从hash表中删除。而hash表中只能通过key去查找,所以node中存放key也是必要的。

好了,到这里这个问题就分析清楚了。上代码:

首先定义结点数据结构:

struct BiListNode{
    int key;
    int val;
    BiListNode *left,*right;
    BiListNode(int k,int x){
        key=k;
        val=x;
        left=NULL;
        right=NULL;
    }
    BiListNode(){
        key=-1;
        val=-1;
        left=NULL;
        right=NULL;
    }
};

LRU

class LRUCache {
public:
    int capacity;
    int size;
    map<int,BiListNode*> listmap;
    BiListNode *head;
    LRUCache(int cap) {
        capacity=cap;
        head=new BiListNode();
        head->left=head;
        head->right=head;
        size=0;
    }
    
    int get(int key) {
        if(listmap.count(key)){
            BiListNode *node=listmap[key];
            if(head->right!=node){
                node->left->right=node->right;
                node->right->left=node->left;

                node->left=head;
                node->right=head->right;
                head->right->left=node;
                head->right=node;
            }
            return node->val;
        }    
        else
            return -1;
    }
    
    void put(int key, int value) {
        BiListNode *node=NULL;
        if(listmap.count(key)){
            node=listmap[key];
            // node after head, update value.
            if(node->left==head){
                node->val=value;
                return ;
            }
            // pick up it and remove from list. 
            else{
                node->left->right=node->right;
                node->right->left=node->left;
                node->val=value;
            }
        }
        // key not in list
        else{
            if(size==capacity){
                //node is the last
                node=head->left;
                listmap.erase(node->key);

                node->val=value;
                node->key=key;
                listmap[key]=node;

                node->left->right=head;
                head->left=node->left;
            }
            else{
                // create new node.
                node=new BiListNode(key,value);
                listmap[key]=node;
                size++;
            }
        }
        // insert node after head.
        node->right=head->right;
        node->left=head;
        head->right->left=node;
        head->right=node;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值