设计LRU缓存结构,该结构在构造时确定大小,假设大小为K,并有如下两个功能。

模拟 LRU缓存结构:http://www.dtmao.cc/news_show_399107.shtml

题目描述

设计LRU缓存结构,该结构在构造时确定大小,假设大小为K,并有如下两个功能
set(key, value):将记录(key, value)插入该结构。
get(key):返回key对应的value值。
[要求] set和get方法的时间复杂度为O(1) 某个key的set或get操作一旦发生,认为这个key的记录成了最常使用的。 当缓存的大小超过K时,移除最不经常使用的记录,即set或get最久远的。 若opt=1,接下来两个整数x, y,表示set(x, y) 若opt=2,接下来一个整数x,表示get(x),若x未出现过或已被移除,则返回-1 对于每个操作2,输出一个答案。

示例1

输入 返回值
[[1,1,1],[1,2,2],[1,3,2],[2,1],[1,4,4],[2,2]],3 [1,-1]
说明
第一次操作后:最常使用的记录为(“1”, 1)
第二次操作后:最常使用的记录为(“2”, 2),(“1”, 1)变为最不常用的
第三次操作后:最常使用的记录为(“3”, 2),(“1”, 1)还是最不常用的
第四次操作后:最常用的记录为(“1”, 1),(“2”, 2)变为最不常用的
第五次操作后:大小超过了3,所以移除此时最不常使用的记录(“2”, 2),加入记录(“4”, 4),并且为最常使用的记录,然后(“3”, 2)变为最不常使用的记录

题目分析
LRU = Least Recently Used (最近最少使用)

本题提示了可供操作的两种方法get和set,而数据类型是key-value模式的,自然想到Map类型去实现;

其次,对最近读取的值(题目要求保存到数组返回),和最近set的值,都是LRU值,那么关键点有两个:

1.在于当map容量达到k值的时候,如果set,需要删除最初保存的值同时put进去最新的值。
2.get获取LRU的map里的值,如果没有,返回-1,存在则返回key对应value,同时要删除key之前在map里面的位置,使用put放入这对key-value。
根据LinkedHashMap的特性,知道他的key是按照顺序存放的,这样删除第一个放进去的值(最不常用的值)很方便。

解题思路
键值对结构,使用HashMap,又有先后顺序,采用LinkedHashMap。
若不使用LinkedHashMap这种现成的结构呢?双向链表,每操作一个值,从原来的位置删除,将其放在链表尾部,尾部是最新的元素,并保持链表长度为k。

public class Solution {
    /**
     * lru design
     * @param operators int整型二维数组 the ops
     * @param k int整型 the k
     * @return int整型一维数组
     */
    
    public int[] LRU (int[][] operators, int k) {
        // write code here
        //使用什么结构,LinkedHashMap
        //链表,头插法
        LinkedHashMap<Integer,Integer> map = new LinkedHashMap<Integer,Integer>();
        ArrayList<Integer> list = new ArrayList<Integer>();
        
        for(int i=0;i<operators.length;i++){
            int[] opt = operators[i];
            if(opt[0] == 1){//set
                if(map.containsKey(opt[1])){//已存在,删除,添加新的
                    map.remove(opt[1]);
                }else{//不存在,添加,判断是否大于k,若大于则删除第一个,若不大于k,则不做操作
                    if(map.size()==k){
                        map.remove(map.keySet().toArray()[0]);
                    }
                }
                map.put(opt[1],opt[2]);
            }else if(opt[0] == 2){//get,获取key元素,并更新元素位置
                if(map.containsKey(opt[1])){
                    list.add(map.get(opt[1]));
                    Integer value = map.remove(opt[1]);
                    map.put(opt[1],value);
                }else{
                    list.add(-1);
                }
                
            }
        }
        
        //将list转化为数组
        int[] res = new int[list.size()];
        for(int i=0;i<list.size();i++){
            res[i] = list.get(i);
        }
        return res;
    }
}

你可能感兴趣的:(数据结构,数据结构,java,面试)