部分文章内容为公开资料查询整理,原文出处可能未标注,如有侵权,请联系我,谢谢。邮箱地址:gnivor@163.com ►►►需要气球么?请点击我吧!

*LeetCode--146.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.

设计最近最久未访问缓存,并实现两个函数get和set,get函数获取一个元素,并更新位置,set添加元素

方法1:使用TreeMap,时间复杂度O(nlogn) ,因为插入TreeMap耗时就是树的高度

//用treemap, 速度很慢.
public class LRUCache2 {
    long timestamp ;
    int capacity;
    int currnum ;
    TreeMap<Long , Integer> tmap ;         //存放时间--key
    HashMap<Integer,Long> hmap_time ;     //存放key--时间
    HashMap<Integer, Integer> hmap;     //存放key--value

    public LRUCache2(int capacity) {
        this.capacity = capacity;        
        currnum = 0;
        tmap = new TreeMap<Long,Integer>();
        hmap_time =new HashMap<Integer,Long>();
        hmap = new HashMap<Integer,Integer>();
    }
    
    public int get(int key) {
        Integer value = hmap.get(key);
        if(value==null) return -1;
        
        long currtime = hmap_time.get(key);
        tmap.remove(currtime);
        timestamp++;
        tmap.put(timestamp, key);
        hmap_time.put(key, timestamp);
        System.out.println("get "+hmap_time);
        return value;
        
    }
    
    public void set(int key, int value) {
        timestamp++;
        if(currnum==capacity&&!hmap.containsKey(key)){
            long deltime = tmap.firstKey();
            int delkey = tmap.firstEntry().getValue();

            tmap.remove(deltime); //删除时间最小的key
            hmap_time.remove(delkey); //删除key对应的时间
            hmap.remove(delkey); //删除key对应的value
            
            tmap.put(timestamp, key);
            hmap_time.put(key,timestamp);
            hmap.put(key, value);
        }else{
            if(!hmap.containsKey(key)){
                currnum++;
                tmap.put(timestamp, key);
                hmap_time.put(key,timestamp);
                hmap.put(key, value);
            }else{
                long currtime = hmap_time.get(key);
                tmap.remove(currtime);
                tmap.put(timestamp, key);
                hmap_time.put(key,timestamp);
                hmap.put(key, value);
            }
        }       
    }
}

 

方法2:使用HashMap和双端队列结合,双端队列控制访问的先后顺序,HashMap用于定位元素

class DLinkedNode {
    int key;
    int value;
    DLinkedNode pre;
    DLinkedNode post;
}

public class LRUCache {
private HashMap<Integer, DLinkedNode> cache = new HashMap<Integer, DLinkedNode>();
    private int count;
    private int capacity;
    private DLinkedNode head, tail; // 头指针和尾指针

    public LRUCache(int capacity) {
        this.count = 0;
        this.capacity = capacity;

        head = new DLinkedNode();
        head.pre = null;

        tail = new DLinkedNode();
        tail.post = null;

        head.post = tail;
        tail.pre = head;
    }

    public int get(int key) {
        DLinkedNode node = cache.get(key);
        if (node == null) {
            return -1; // should raise exception here.
        }
        // move the accessed node to the head;
        this.moveToHead(node);
        return node.value;
    }

    public void set(int key, int value) {
        DLinkedNode node = cache.get(key);
        if (node == null) {
            DLinkedNode newNode = new DLinkedNode();
            newNode.key = key;
            newNode.value = value;

            this.cache.put(key, newNode);
            this.addNode(newNode);
            count++;

            if (count > capacity) {
                // pop the tail
                DLinkedNode tail = this.popTail(); // 删除链表元素                
                this.cache.remove(tail.key); // 删除value                
                --count;
            }
        } else {
            // update the value.
            node.value = value;
            this.moveToHead(node);
        }
    }
    // Always add the new node right after head;
    private void addNode(DLinkedNode node) {
        node.pre = head;
        node.post = head.post;

        head.post.pre = node;
        head.post = node;
    }

    //Remove an existing node from the linked list.
    private void removeNode(DLinkedNode node) {
        DLinkedNode pre = node.pre;
        DLinkedNode post = node.post;

        pre.post = post;
        post.pre = pre;
    }

    //Move certain node in between to the head.
    private void moveToHead(DLinkedNode node) {
        this.removeNode(node);
        this.addNode(node);
    }

    // pop the current tail.
    private DLinkedNode popTail() {
        DLinkedNode res = tail.pre;
        this.removeNode(res);
        return res;
    }
}

 

posted @ 2015-09-25 14:49  流了个火  阅读(133)  评论(0)    收藏  举报
►►►需要气球么?请点击我吧!►►►
View My Stats