`

Lru Cache

 
阅读更多

 

题目:https://leetcode.com/problems/lru-cache/

大学课本在讲操作系统的时候提及LRU可基于双向链表以及map来实现: 其中双向链表用于调整优先级,根据LRU规则淘汰对象; map主要用于快速查询。

 

将题目分解:

  • get 操作涉及优先级调整
  • set 操作涉及优先级调整以及淘汰操作

将题目转化为实现head()以及evict()两个函数;

  • evict 淘汰队尾,有两种情况  1)队尾前面无节点,即:又是队首又是队尾 2)前面有节点
  • head 将操作的节点放到队首,如果已经位于队首则无需操作: 1)这个元素之前已经存在于队列中 2)这个元素是新的
解题代码:
package org.bull.leetcode.alg;

import java.util.HashMap;
import java.util.Map;

/**
 * Created by bull on 16/5/5.
 * <p>
 * https://leetcode.com/problems/lru-cache/
 * get时涉及优先级调整
 * set时涉及优先级调整以及淘汰操作
 * 将问题化简为:实现 head以及evict函数
 * <p>
 * evict其实就是淘汰队尾:有两种情况 1)队尾前面无节点,即:又是队首又是队尾 2)前面有节点
 * head 就是将操作的节点放到队首,如果已经位于队首则无需操作: 1)这个元素之前已经存在于队列中 2)这个元素是新的
 */
public class LRUCache {
    private int capacity;
    /**
     * 用来保存队首,优先级调整基本针对队首
     */
    private Entry head;
    /**
     * 淘汰对象基本针对队尾
     */
    private Entry tail;

    private Map<Integer, Entry> container;

    public LRUCache(int capacity) {
        this.capacity = capacity;
        container = new HashMap<>(capacity);
    }

    /**
     * 获取对象,并调整优先级
     *
     * @param key
     * @return
     */
    public int get(int key) {
        Entry entry = container.get(key);
        if (entry == null) {
            return -1;
        }
        head(entry, true);
        return entry.getValue();
    }

    /**
     * 设置对象,如果达到阈值,淘汰队尾对象
     *
     * @param key
     * @param value
     */
    public void set(int key, int value) {
        if (container.get(key) == null) {
            if (container.size() >= capacity) {
                evict();
            }
            Entry entry = new Entry();
            entry.setKey(key);
            entry.setValue(value);
            head(entry, false);
            container.put(key, entry);
        } else {
            Entry entry = container.get(key);
            entry.setValue(value);
            head(entry, true);
        }
    }

    /**
     * 淘汰队尾
     */
    public void evict() {
        Integer tailKey = tail.getKey();
        container.remove(tailKey);
        //调整队尾
        Entry before = tail.before;
        if (before == null) {
            head = null;
            tail = null;
        } else {
            before.next = null;
            tail.before = null;
            tail = before;
        }
    }

    /**
     * 将优先级置顶
     *
     * @param entry
     */
    public void head(Entry entry, boolean in) {
        if (in) {
            if (entry.before != null) {
                entry.before.next = entry.next;
                if (entry.next == null) {//队尾
                    tail = entry.before;
                } else {
                    entry.next.before = entry.before;
                }
                //调整队首
                entry.before = null;
                head.before = entry;
                entry.next = head;
                head = entry;
            }
        } else {
            if (container.size() > 0) {//已经有元素
                entry.next = head;
                head.before = entry;
                head = entry;
            } else { //特点是 head 和 tail 都不存在
                head = entry;
                tail = entry;
            }
        }
    }

    /**
     * 双向链表结构体
     */
    class Entry {
        private int key;
        private int value;
        private Entry next;
        private Entry before;

        public int getValue() {
            return value;
        }

        public void setValue(int value) {
            this.value = value;
        }

        public Entry getNext() {
            return next;
        }

        public void setNext(Entry next) {
            this.next = next;
        }

        public Entry getBefore() {
            return before;
        }

        public void setBefore(Entry before) {
            this.before = before;
        }

        public int getKey() {
            return key;
        }

        public void setKey(int key) {
            this.key = key;
        }
    }
}
  

总结来说,解题首先思路要对,然后要分解问题,分解问题是要全面考虑,然后有耐心一步步的去实现即可。

 

分享到:
评论

相关推荐

    算法面试通关40讲完整课件 57-58 LRU Cache

    算法面试通关40讲完整课件 57-58 LRU Cache 算法面试通关40讲完整课件 57-58 LRU Cache 算法面试通关40讲完整课件 57-58 LRU Cache 算法面试通关40讲完整课件 57-58 LRU Cache 算法面试通关40讲完整课件 57-58 LRU ...

    最近最少使用cache,提取leveldb的lru cache部分,增加过期时间,过期失效

    提取google开源软件leveldb的lru cache部分,独立出来,并增加过期时间,过期失效,可独立使用。仅供参考。

    LRU Cache的简单C++实现

     LRU Cache是一个Cache的置换算法,含义是“近少使用”,把满足“近少使用”的数据从Cache中剔除出去,并且保证Cache中第一个数据是近刚刚访问的,因为这样的数据更有可能被接下来的程序所访问。  LRU的应用比较...

    Android性能优化一 : 1.The Magic of LRU Cache (100 Days of Google Dev)

    谷歌官方视频

    LRU-update-Cache-.zip_LRU cache

    LRU置换算法是选择最近最久未使用的页面予以置换。该算法赋予每个页面一个访问字段,用来记录一个页面自上次被访问以来经历的时间T,当须淘汰一个页面时,选择现有页面中T值最大的,即最近最久没有访问的页面。这是...

    Lru Cache java代码

    LruCache的java代码实现,是从android代码中抽取出来的

    erlang lru cache module

    NULL 博文链接:https://erlangdisplay.iteye.com/blog/315483

    ARM高速缓存(Cache)Verilog代码 包含ISE工程

    Cache替换策略: LRU I_Cache的工作就是在cpu需要指令时将指令从主存中搬进I_Cache,再传给CPU,而D_Cache在解决数据读外,还要注意数据写入的问题。本工程可以与arm.v 中的arm 核协同工作,主存使用dram_ctrl_sim。

    lru-cache-js:使用双链表和映射实现 LRU Cache,读写时间复杂度为 O(1)

    LRU缓存使用的数据结构使用双向链表实现的队列。 队列的最大大小将等于...执行 npm i lru-cache-js-map const LRUCache = require('lru-cache-js-map');var cache = new LRUCache(100);for(var i=0; i &lt; 100; i++){

    Python实现的一个简单LRU cache

    python的dict 是一个非常简单的cache,但是由于数据量很大,内存很可能增长的过大,因此需要限定记录数,并用LRU算法丢弃旧记录。key 是整型,value是10KB左右的python对象 分析: 1)可以想到,在对于cache,我们...

    LRU更新Cache

    是计算机体系结构试验程序,用LRU算法更新Cache

    javalruleetcode-LRU_cache:LRU_cache

    LRU_cache (Leetcode 146) 设计和实现最近最少使用 (LRU) 缓存的数据结构。 它应该支持以下操作:get 和 set。 get(key) – 如果键存在于缓存中,则获取键的值(将始终为正),否则返回 -1。 set(key, value) – ...

    javalruleetcode-LRUCache:LeetCode问题146Java中的LRU缓存

    Cache in Java 我很喜欢这个问题。 我在康奈尔大学的第一个 CS 课程涉及队列和其他数据结构。 对于其中一个课堂项目,我们必须开发基于队列的模拟。 在工作中,我开发了广泛的队列库。 我能说什么; 我喜欢队列和...

    lru_cache_demo

    如果要使用图片Cache, Android官网和都建议使用LRU Cache,他可以限定cache的大小并且把最少使用的cache清除掉。 所以我们用ListView呈现从网路上抓下来的图片 private String [] mImgsPath = { " ...

    lrucacheleetcode-LRU_Cache_Algorithm:用C++实现LRU缓存算法

    lru cache leetcode LRU Cache Algorithm (LRU缓存算法) C++版本,适用于 ##LRU算法介绍 引自: Discards the least recently used items first. This algorithm requires keeping track of what was used when, ...

    backports.functools_lru_cache

    在发布的Python 3.3中的functools.lru_cache的反向。 用法 考虑使用此技术导入“ lru_cache”函数: try: from functools import lru_cache except ImportError: from backports.functools_lru_cache import lru_...

    LRU Cache-开源

    该项目将利用LRU(最近使用)算法开发内存中对象缓存。 缓存将在固定大小的内存池中存储最常访问的对象。 因此,系统保持统计并计算折衷。

    算法训练营第二天1

    然后,课程讲解了 LRU Cache 的基本概念,包括如何使用哈希表和链表来实现 LRU Cache,如何处理缓存命中和缓存miss的情况等。 在 LRU Cache 部分,课程还讲解了如何使用双向链表来实现 LRU Cache,如何使用哈希表来...

    lru-cache:C ++中功能完整的LRU缓存实现

    lru-cache:C ++中功能完整的LRU缓存实现

    java 缓存 cache lru 实例

    java 缓存 cache lru 实例 java 缓存 cache lru 实例 java 缓存 cache lru 实例 java 缓存 cache lru 实例 java 缓存 cache lru 实例 java 缓存 cache lru 实例 java 缓存 cache lru 实例

Global site tag (gtag.js) - Google Analytics