Leetcode 146. LRU Cache

来源:互联网 发布:大圣传 知乎 编辑:程序博客网 时间:2024/05/16 18:17

146. LRU Cache

Total Accepted: 68216 Total Submissions: 432816 Difficulty: Hard

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.


一开始用了俩数组,结果发现理解题意有偏差。trick的地方在于,到达容量之后,题目中废除了old key和old value,插入了新的key和value。如果是固定长度的数组,那么get元素时候就会有问题。比如容量是5,LRU对应的key是2,那么当插入新元素是6的时候,废除了2,没问题,插入却插入到了1,这样获取的时候就错了。而且很明显也重改写了本来的元素。


博主的理解是容量这个变量只是为了将大于它的很久没有用的值去除,是个烟雾弹,真正的保存数据的长度肯定大于这个值,因为它是有地方给新的key储存的。


先写了一个小时,写了个HashMap+数组的版本。while循环忘记变量自减结果直接移步IDE DEBUG。。终于发现问题,改好如下:

public class LRUCache {    HashMap<Integer,Integer> hm = new HashMap<Integer, Integer>();    int[] time;    int size;        public LRUCache(int capacity) {        size = capacity;        time = new int[size];                for (int i=0; i<size; i++){            time[i]=-1;        }    }        public int get(int key) {        if(hm.containsKey(key)){            shift(time, key);            return hm.get(key);        }else{            return -1;        }    }        public void set(int key, int value) {        if(hm.size()==size){            if (!hm.containsKey(key)){            hm.remove(time[size-1]);            time[size-1]=-1;            }            hm.put(key, value);            shift(time, key);        }else{            hm.put(key, value);            shift(time, key);        }    }        void shift(int[] time, int key){        int pos = -1, last = -1;        for(int i=0; i<size; i++){            if (time[i]==key){                pos = i;break;            }else if (time[i]==-1){                last = i;break;            }        }                if (pos!=-1){ // find key match            while(pos>=1){                 time[pos]=time[pos-1];pos--;            }            time[0]=key;        }else if(last == -1){ // full && no key match            pos = size-1;            while(pos>=1){                 time[pos]=time[pos-1];pos--;            }            time[0]=key;        }else{ // no key match but not full            pos=last;            while(pos>=1){                 time[pos]=time[pos-1];pos--;            }            time[0]=key;        }    }}

直接提示TLE,于是上网搜索,问题在于不应该有O(N)的东西出现。比如自己的代码中shift就是O(N)。


每次操作都要维护cache DBL队列的头结点(其实就是放在了开始);如果MAP满了,必须先在cache队列中remove这个元素,然后再加入hm并更新cache序列头结点。

public class LRUCache { // 23ms    Map<Integer, DBL> hm = new HashMap<Integer, DBL>();    int size;    DBL head;    DBL tail;        public LRUCache(int capacity) {        this.size = capacity;    }        public int get(int key) {        if(hm.containsKey(key)){            remove(hm.get(key)); // 从cache队列中删除该节点            setHead(hm.get(key)); // 更新当前cache序列头元素            return hm.get(key).val;        }else{            return -1;        }    }        public void set(int key, int value) {        if(hm.containsKey(key)){            remove(hm.get(key)); // 从cache队列中删除该节点            setHead(hm.get(key)); // 更新当前cache序列头元素            hm.get(key).val = value;        }else{            DBL node = new DBL(key, value);            if(hm.size() == size) {                hm.remove(tail.key); // 移除最后一个元素                remove(tail); // 修饰tail元素            }            setHead(node);  // 更新当前cache序列头元素            hm.put(key, node);        }    }        public void setHead(DBL node){ // 更新当前cache序列头元素        node.next = head;        if(head != null) head.pre = node;        head = node;        if(tail == null) tail = head;    }        public void remove(DBL node){ // 从cache队列中删除该节点        if(node == head && node == tail){            head = null; tail = null;        }else if(node != head && node == tail){            tail.pre.next = null; tail = tail.pre;        }else if(node == head && node != tail){            head.next.pre = null; head = head.next;        }else{            node.pre.next = node.next;            node.next.pre = node.pre;        }    }        public class DBL{        int val;        int key;        DBL pre;        DBL next;                DBL(int key, int val){            this.key = key;            this.val = val;        }    }}


0 0
原创粉丝点击