设计LRU缓存结构(Java版)

本文介绍了如何使用Java实现LRU(最近最少使用)缓存结构,包括基于LinkHashMap、HashMap+队列以及手动实现链表的三种方法。每种方法都保证了set和get操作的时间复杂度为O(1),并详细展示了每种解法的代码实现。
摘要由CSDN通过智能技术生成

描述

设计LRU(最近最少使用)缓存结构,该结构在构造时确定大小,假设大小为 k ,并有如下两个功能

1. set(key, value):将记录(key, value)插入该结构

2. get(key):返回key对应的value值

提示:

1.某个key的set或get操作一旦发生,认为这个key的记录成了最常使用的,然后都会刷新缓存。

2.当缓存的大小超过k时,移除最不经常使用的记录。

3.输入一个二维数组与k,二维数组每一维有2个或者3个数字,第1个数字为opt,第2,3个数字为key,value

若opt=1,接下来两个整数key, value,表示set(key, value)

若opt=2,接下来一个整数key,表示get(key),若key未出现过或已被移除,则返回-1

对于每个opt=2,输出一个答案

4.为了方便区分缓存里key与value,下面说明的缓存里key用""号包裹

要求:set和get操作复杂度均为 O(1)O(1)

示例1

输入:

[[1,1,1],[1,2,2],[1,3,2],[2,1],[1,4,4],[2,2]],3

返回值:[1,-1]

说明:

[1,1,1],第一个1表示opt=1,要set(1,1),即将(1,1)插入缓存,缓存是{"1"=1}

[1,2,2],第一个1表示opt=1,要set(2,2),即将(2,2)插入缓存,缓存是{"1"=1,"2"=2}

[1,3,2],第一个1表示opt=1,要set(3,2),即将(3,2)插入缓存,缓存是{"1"=1,"2"=2,"3"=2}

[2,1],第一个2表示opt=2,要get(1),返回是[1],因为get(1)操作,缓存更新,缓存是{"2"=2,"3"=2,"1"=1}

[1,4,4],第一个1表示opt=1,要set(4,4),即将(4,4)插入缓存,但是缓存已经达到最大容量3,移除最不经常使用的{"2"=2},插入{"4"=4},缓存是{"3"=2,"1"=1,"4"=4}

[2,2],第一个2表示opt=2,要get(2),查找不到,返回是[1,-1]

示例2

输入:[[1,1,1],[1,2,2],[2,1],[1,3,3],[2,2],[1,4,4],[2,1],[2,3],[2,4]],2

返回值:[1,-1,-1,3,4]

第一种解法

利用java的LinkHashMap来实现,实现比较简单,代码如下

public static int[] firstLRU (int[][] operators, int k) {
        // write code here
        LinkedHashMap<Integer,Integer> map = new LinkedHashMap<>();
        if(operators == null || operators.length < 1 || k < 1){
            return null;
        }
        List<Integer> list = new ArrayList<>();
        for (int i = 0; i < operators.length; i++) {
            if(map.size() > k){
                Integer next = map.keySet().iterator().next();
                map.remove(next);
            }
            int[] arr = operators[i];
            int opt = arr[0];
            int key =  arr[1];
            if(opt == 1){
               int value = arr[2];
               map.put(key,value);
            }else {
                Integer integer = map.get(key);
                if(integer == null){
                    list.add(-1);
                }else {
                    map.remove(key);
                    map.put(key,integer);
                    list.add(integer);
                }
            }
        }
        int[] result = new int[list.size()];
        for (int i = 0; i < list.size(); i++) {
            result[i] = list.get(i);
        }
        return result;
    }

第二种解法

由于第一种解法,我们使用了java自带的工具类LinkHashMap,第二种解法,我们就利用map + 队列来实现。代码如下

public static int[] secondLRU (int[][] operators, int k) {
    HashMap<Integer,Integer> map = new HashMap<>();
    Queue<Integer> queue = new LinkedList<>();
    List<Integer> list = new ArrayList<>();
    for (int i = 0; i < operators.length; i++) {
        if(queue.size() > k){
            Integer poll = queue.poll();
            map.remove(poll);
        }
        int[] arr = operators[i];
        int opt = arr[0];
        int key = arr[1];
        if(opt == 1){
            int value = arr[2];
            queue.add(key);
            map.put(key,value);
        }else {
            Integer integer = map.get(key);
            if(integer == null){
                list.add(-1);
            }else {
                list.add(integer);
                queue.remove(key);
                queue.add(key);
            }
        }
    }
    int[] result = new int[list.size()];
    for (int i = 0; i < list.size(); i++) {
        result[i] = list.get(i);
    }
    return result;
}

第三种解法

由于第一种解法,我们使用了java自带的工具类LinkHashMap,第二种解法,我们利用map + 队列来实现,第三种解法,我们利用map+手动实现链表来解决。代码如下

static Node head = null;
static int count = 0;
public static int[] thirdLRU (int[][] operators, int k) {
     if(operators == null || operators.length < 1 || k < 1){
         return null;
     }
     HashMap<Integer,Integer> map = new HashMap<>();
     List<Integer> list = new ArrayList<>();
     for (int i = 0; i < operators.length; i++) {
         if(count > k){
             int remove = deleteHead();
             map.remove(remove);
         }
         int[] arr = operators[i];
         int opt = arr[0];
         int key = arr[1];
         if(opt == 1){
             int value = arr[2];
             addEnd(key);
             map.put(key,value);
         }else {
             Integer integer = map.get(key);
             if(integer == null){
                 list.add(-1);
             }else {
                 list.add(integer);
                 deleteByNode(key);
                 addEnd(key);
             }
         }
     }
     int[] result = new int[list.size()];
     for (int i = 0; i < list.size(); i++) {
         result[i] = list.get(i);
     }
     return result;
}


private static void deleteByNode(Integer key){
     Node node = head;
     Node pre = null;
     if(node == null){
         return;
     }
     while (node != null && !node.item.equals(key)){
         pre = node;
         node = node.next;
     }
     if(pre == null){
         head = head.next;
     }else {
         if(node == null){
             return;
         }else {
             pre.next = node.next;
         }
     }
     count--;
}



public static void addEnd(int key){
     Node node = new Node(key);
     Node tem = head;
     count ++;
     if(head == null){
         head = node;
     }else {
         while (true){
             Node n = tem;
             tem = tem.next;
             if(tem == null){
                 n.next = node;
                 break;
             }
         }
     }

}


private static int  deleteHead(){
     if(head == null){
         return -1;
     }
     count --;
     Integer item = head.item;
     head = head.next;
     return item;
}


  static class Node{
     Node next;
     Integer item;
     public Node(Integer item){
         this.item = item;
     }

}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值