牛客题霸NC93设计LRU缓存结构Java题解

牛客题霸NC93设计LRU缓存结构Java题解

https://www.nowcoder.com/practice/e3769a5f49894d49b871c09cadd13a61?tpId=117&&tqId=35015&rp=1&ru=/ta/job-code-high&qru=/ta/job-code-high/question-ranking

方法:HashMap+双向链表
解题思路:先通过遍历operators数组,将set和get操作区分开。利用HashMap存储双向链表中节点的key和节点的映射<key,Node>,其中Node为双向链表的节点<key,value>
get操作:先判断map中是否存在key,如果map不存在key 则返回-1;如果map存在key,先将该key的结点删除,然后再将此节点插入到链表的表头。
set操作:先判断map中是否存在key, 如果已经存在key,将val更新,并删除这个节点,再将node插入到表头,如果不存在key,先判断是否超出空间,如果超出先在链表和map删除最后一个节点,再将节点插入到表头,并将对应的映射添加到map中。

import java.util.*;
 
 
public class Solution {
    /**
     * lru design
     * @param operators int整型二维数组 the ops
     * @param k int整型 the k
     * @return int整型一维数组
     */
    public class Node{
        private int val;
        private int key;
        private Node pre =null;
        private Node next =null;
        private Node(int key,int val){
            this.val=val;
            this.key=key;
        }
    }
 
    private HashMap<Integer,Node> map = new HashMap();
    private Node head = new Node(-1,-1);  //头节点
    private Node tail = new Node(-1,-1);  //尾节点
    private int k=0;
 
    public int[] LRU (int[][] operators, int k) {
        // write code here
        this.k = k;
        head.next = tail;
        tail.pre = head;
 
        int len = (int)Arrays.stream(operators).filter(x->x[0]==2).count();  //获取数组中开头为2(get操作)的元素个数       
        int res[] = new int[len];
 
        for(int i=0,j=0;i<operators.length;i++){
            if(operators[i][0] == 1){   //获取数组中开头为1(set操作)的元素个数
                set(operators[i][1],operators[i][2]);  //set(key,val)
            }else{   //获取数组中开头为2(get操作)的元素个数
                res[j++] = get(operators[i][1]);  //get(key)
            }
        }
        return res;
    }
 
    public void set(int key,int val){
        //判断是否存在key
        Node node = null;
        if(map.containsKey(key)){   //如果已经存在key,将val更新,并删除这个节点,再将node插入到表头
            node = map.get(key);
            node.val = val;
            //删除该结点
            node.next.pre = node.pre;
            node.pre.next = node.next;
            //将node节点提到第一个
            moveToFirst(node);
        }else{  //如果不存在key,先判断是否超出空间,如果超出先在链表和map删除最后一个节点,再将节点插入到表头,并将对应的映射添加到map中
            if(map.size()==k){
                //在map中删除映射到最后一个节点的key
                int keyremove =tail.pre.key;
                map.remove(keyremove);
                //在链表中删除最后一个节点
                tail.pre.pre.next = tail;
                tail.pre = tail.pre.pre;
            }
            node = new Node(key,val);
            //在map中添加对新节点的映射
            map.put(key,node);
            //将节点插入到表头
            moveToFirst(node);
 
        }
    }
 
    public int get(int key){
        // 如果不存在key 则返回-1
        // 如果存在key,先将该key的结点删除,然后再将此节点插入到链表的表头
        if(!map.containsKey(key)){
            return -1;
        }else{
            Node node = map.get(key);
            //删除该结点
            node.next.pre = node.pre;
            node.pre.next = node.next;
            //插入到表头
            moveToFirst(node);
            return node.val;
        }
    }
    //将节点插入到表头
    public void moveToFirst(Node node){
            head.next.pre =node;
            node.next =head.next;
            node.pre =head;
            head.next=node;
    }
}

 

posted @ 2020-11-25 09:45  云飞扬°  阅读(331)  评论(0编辑  收藏  举报