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

设计LRU缓存结构

http://www.nowcoder.com/questionTerminal/e3769a5f49894d49b871c09cadd13a61

方法: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;
    }
}
全部评论

相关推荐

Hyh_111:像这种hr就不用管了,基本没啥实力,换一个吧
点赞 评论 收藏
分享
今天 16:33
门头沟学院 Java
本人某中9本科,成绩中等,目前没科研没实习,目前后端学到了javaWeb,开始没定好方向,在学国外课程,走工程路线起步有点晚了,到这个时间点了还在学JavaWeb,顿感迷茫,不知道是坚持走下去还是寒假去准备考研。考研这个路弄得我还是心痒痒的,因为从众考研的人也不在少数,所以会有这方面的心理安慰吧,就是“不行我可以去考研啊”,而且意味着三年的缓冲,为了复试还有积攒经验美化简历,其实现在也可以去申入实验室打杂;就业可能意味着多些工作经验,工程岗应该到后面还是经验大于学历?还是有点迷茫了,求助好心人有无路线启发
千千倩倩:同27给点建议,现在这个时间点可以快速看完外卖和点评,不用跟着敲,但一定要在看的时候总结每个部分的整个业务流程,对其中的实现有一个大概的印象。然后直接开始看八股,刷算法。八股和算法最好还是在项目学习中穿插着看。如果计算机基础,算法这些基础好,加上每天刻苦学习,两周可以达到勉强能面试的水平,到时候就直接海投中小厂,在约面和面试的过程中不断巩固知识。没找到实习也没关系,就当积累经验。再沉淀一波直接明年三月开始投暑期,毕竟是9本,总是有面试机会的,只要你这三个月不懈怠,面试发挥得一定不错,只要拿到一个中,大厂暑期实习,秋招就有竞争力了。总得而言,现在还有机会,但是时间非常紧张,需要你结合自己情况考虑,共勉
你会选择考研还是直接就业
点赞 评论 收藏
分享
评论
2
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务