LeetCode之路2,LRUCache 最近最少使用算法

恩...安卓实训终于做完了 这边继续开更

很多简单的题目慢慢来更把,首先解决接受率比较低的

这次做的是LRUCache

原题如下

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.

首先想到的是这样的思路

  • 使用单链表来存
  • 主类里存的是头结点 尾结点
  • 每次get遍历从head结点开始,直到找到或者到头为止
  • 每次put如果是已经有的key,修改其值,并放到链表尾
  • 如果是没有的值则新建一个结点放到尾巴上
  • 如果容量满了则去删改头结点

代码如下

package lru.cache;

public class LRUCache2 {

    private Item head,tail;
    private Integer capacity;
    private Integer count;
    
    public LRUCache2(int capacity) {
        this.capacity = capacity;
        count= 0;
        head = null;
        tail = null;
    }
    
    public int get(int key) {
        if(head == null)
            return -1;
        if(head.key == key)
            return head.value;
        if(tail.key == key)
            return tail.value;
        
        Item theValue = head.next;
        Item theValueBefore = head;
        while(theValue != null){
            if(theValue.key == key ){
                theValueBefore.next = theValue.next;
                tail.next = theValue;
                tail = theValue;
                theValue.next = null;
                return theValue.value;
            }
            theValueBefore = theValue;
            theValue = theValue.next;
        }
        return -1;

    }
    
    public void set(int key, int value) {
        if(head == null){
            head = new Item(value, key, null);
            tail = head;
        }
        Item temp = checkKeyPresent(key);
        if(temp != null){
            temp.value = value;
        }else{
            if(capacity.equals(count)){
                head = head.next;
                tail.next = new Item(value, key, null);
                tail = tail.next;
            }else{
                tail.next = new Item(value, key, null);
                tail = tail.next;
                count ++ ;              
            }
        }
    }
    
    public Item checkKeyPresent(int key){
        Item temp = head ;
        while(temp != null){
            if(temp.key == key )
                return temp;
            temp = temp.next;
        }
        return null;
    }
    class Item{
        public int value;
        public int key;
        public Item next;
        public Item(int value, int key, Item next) {
            super();
            this.value = value;
            this.key = key;
            this.next = next;
        }

    }
}

这样的做的结果是

这个方法在capacity=2048时 timeout

超时了啊...

好吧,从新审视一下

最耗时间的部分是set时需要
遍!历!已!经!有!的!全!部!结!点!
那么如果没有这个过程,或者这个过程消耗时间极短,效率应该会大幅上升再想KYY VALUE 好吧

hashMap就决定是你了!

而为了维护最近最少使用这一点, 还是维护链表最为方便,如果使用数组很难记录最近使用这个数值

对上述代码进行修改!

所以Key将作为索引,本质还是一个双向链表

talk is cheap,show you the code

更多的问题看注释就好

package lru.cache;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
/*
 * 之前用链表写的效率太差
 * 仔细检查代码
 * 发现最耗时间的部分是set时
 * 遍!历!已!经!有!的!全!部!结!点!
 * 那么如果没有这个过程,或者这个过程消耗时间极短
 * 就可以了...再想KYY VALUE 好吧 
 * hashMap就决定是你了!
 * 而为了维护最近最少使用这一点
 * 还是维护链表最为方便,如果使用数组很难记录最近使用这个数值
 * 所以对上述代码进行修改!
 * 所以Key将作为索引,本质还是一个链表
 */
public class LRUCache {

    private HashMap<Integer, Item> cache;
    private Item head, tail;
    private int capacity;
    private int count;
    
    public LRUCache(int capacity) {
        cache = new HashMap<Integer, LRUCache.Item>(capacity);
        this.capacity = capacity;
        count= 0;
        head = null;
        tail = null;
    }
    
    public int get(int key) {
        if(cache.isEmpty())
            return -1;
        
        if(!cache.keySet().contains(key))
            return -1;

        Item temp = cache.get(key);
        //分4种情况,分别为既是头结点又是尾结点、只是头结点、
        //只是尾结点和既不是头结点又不是尾结点
        if(temp.previous == null && temp.next ==null){
            return temp.value;
        }else if(temp.previous == null){
            head = temp.next;
            head.previous = null;
            tail.next = temp;
            temp.previous = tail;   
            tail = temp;
            temp.next = null;
            return temp.value;
        }else if(temp.next == null){
            return temp.value;
        }else{
            temp.previous.next = temp.next;
            temp.next.previous = temp.previous;
            temp.previous = tail;
            tail.next = temp;
            temp.next = null;
            tail = temp;
            return temp.value;
        }

    }
    
    public void set(int key, int value) {
        if(cache.isEmpty()){
            head = new Item(key,value);
            tail = head;
            cache.put(key, head);
            count ++;
            return;
        }
                
        Item temp = cache.get(key);
        if(temp != null){
            //如果存在,则修改该值,并且放到尾结点
            temp.value = value;
            
            if(head == tail){
                //如果是头结点又是尾结点
                //null
            }else if(temp.previous == null && temp.next != null){
                //如果只是头节点
                head = temp.next;
                head.previous = null;
                tail.next = temp;
                temp.previous = tail;
                tail = temp;
            }else if(temp.next == null && temp.previous != null){
                //如果只是尾结点
                //null
            }else {
                temp.next.previous = temp.previous;
                temp.previous.next = temp.next;
                tail.next = temp;
                temp.previous = tail;
                temp.next = null;
                tail = temp;
            }
        }else{
            //如果不存在
            if(capacity > count ){
                //不存在,且内容没满,则新建一个结点,放到尾部
                temp = new Item(key,value);
                tail.next = temp;
                temp.previous = tail;
                tail = temp;
                count ++ ; 
                cache.put(key, temp);
            }else{
                //不存在且内容已满,则修改头结点中内容,并放到尾巴上
                if(head == tail){
                    temp = head;
                    
                    cache.remove(temp.key);
                    temp.value = value;                 
                    temp.key = key;
                    
                    cache.put(key, head);
                }else{
                    temp = head;
                    cache.remove(temp.key);
                    temp.value = value; 
                    temp.key = key;
                    head = head.next;
                head.previous = null;
                temp.next = null;
                    tail.next = temp;
                    temp.previous = tail;
                    tail = temp;
                    cache.put(key, temp);
                }

            }
        }
    }
    
    class Item{
        public int value;
        public int key;
        public Item previous;
        public Item next;
        public Item(int key,int value) {
            super();
            this.value = value;
            this.key = key;
            this.next = null;
            this.previous = null;
        }

    }

}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,133评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,682评论 3 390
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,784评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,508评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,603评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,607评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,604评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,359评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,805评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,121评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,280评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,959评论 5 339
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,588评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,206评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,442评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,193评论 2 367
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,144评论 2 352

推荐阅读更多精彩内容

  • 我委在柔软的沙发里,想着岁月赠我的点滴,节日依黄昏,孤单痴冥想,未来可期否?欲奔向远方踏寻,千山万水蝶飞舞,草木青...
    amanda_green阅读 135评论 0 0
  • 是的!从今天开始,全中国一年一次的全民大迁徙——春运就要开始了! 不论你是刚考完试的学生族小单身狗,还是打完述职报...
    臭不要脸妖阅读 9,924评论 0 14
  • 题目 来源: 优达学城--编程基础:python内容:使用 turtle 画出你想象。效果演示: 我的解法 步骤 ...
    codinghjy阅读 811评论 0 0
  • 中国是世界上最早发行和流通纸币的国家,宋元明清四朝都曾经印行过纸币。而作为官方发行的唯一纸币,明朝只有“大明宝钞”...
    一夕厘阅读 2,097评论 0 0
  • 从来没有一个时代,像现在一样迅捷、开放、海量信息随手拈来。我们从公众号上获取各种好玩有趣、新鲜奇怪、干货有料的信息...
    幸福的眼泪阅读 1,044评论 1 3