【刷题1】LeetCode 146. LRU缓存机制 java题解

重点

1.构造链表的Node类,需要有值key、value、节点prev、next5
2.链表要有head伪头节点和tail伪尾节点
3.缓存用hashmap
4.size记录数量
5.为了避免重复代码,除了get、put外,我们还有以下方法:delete删除节点、deleteTail删除尾节点、addToHead加到头节点、removeToHead移到头节点。

题目

https://leetcode-cn.com/problems/lru-cache/
【刷题1】LeetCode 146. LRU缓存机制 java题解_第1张图片

代码

class LRUCache {
    class DLinkedNode{
        int key;
        int value;
        DLinkedNode prev;
        DLinkedNode next;
        public DLinkedNode(){
        }
        public DLinkedNode(int _key,int _value){
            key=_key;
            value=_value;
        }
    }

    private Map<Integer,DLinkedNode> cache=new HashMap<Integer,DLinkedNode>();
    private int size;
    private int capacity;
    private DLinkedNode head,tail;

    public LRUCache(int capacity) {
        this.size=0;
        this.capacity=capacity;
        //使用伪头部和伪尾部节点
        head=new DLinkedNode();
        tail=new DLinkedNode();
        head.next=tail;
        tail.prev=head;
    }
    
    public int get(int key) {
        DLinkedNode node=cache.get(key);
        if(node==null){
            return -1;
        }
        //如果key存在,先通过哈希表定位,再移到头部
        moveToHead(node);
        return node.value;
    }
    
    public void put(int key, int value) {
        DLinkedNode node=cache.get(key);
        if(node==null){
            //如果key不存在,创建一个新的节点
            DLinkedNode newNode=new DLinkedNode(key,value);
            //添加进哈希表
            cache.put(key,newNode);
            //添加至双向链表的头部
            addToHead(newNode);
			//计数+1
            ++size;
            if(size>capacity){
                //如果超出容量,删除双向链表的尾部节点
                DLinkedNode tail=removeTail();
                //删除哈希表中对应的项
                cache.remove(tail.key);
                --size;//计数-1
            }
        }
        else{
            //如果key存在.修改value
            node.value=value;
            //并移到头部
            moveToHead(node);
        }
    }

	//加到头部
    private void addToHead(DLinkedNode node){
        node.prev=head;
        node.next=head.next;
        head.next.prev=node;
        head.next=node;
    }
    //删除节点
    private void removeNode(DLinkedNode node){
        node.prev.next=node.next;
        node.next.prev=node.prev;
    }
    //移动到头部
    private void moveToHead(DLinkedNode node){
        removeNode(node);
        addToHead(node);
    }
    //删除尾节点
    private DLinkedNode removeTail(){
        DLinkedNode res=tail.prev;
        removeNode(res);
        return res;
    }
}

/**
 * Your LRUCache object will be instantiated and called as such:
 * LRUCache obj = new LRUCache(capacity);
 * int param_1 = obj.get(key);
 * obj.put(key,value);
 */
class LRUCache {
    class Node{
        int key;
        int val;
        Node prev;
        Node next;
        Node(){
        }
        Node(int key,int val){
            this.key=key;
            this.val=val;
        }
    }
    HashMap<Integer,Node> map;
    Node head,tail;
    int capacity;
    int size;
    public LRUCache(int capacity) {
        map=new HashMap<>();
        head=new Node();
        tail=new Node();
        head.next=tail;
        tail.prev=head;
        this.capacity=capacity;
        this.size=0;
    }
    
    public int get(int key) {
        if(map.containsKey(key)){
            Node node=map.get(key);
            moveToHead(node);
            return node.val;
        }
        return -1;
    }
    
    public void put(int key, int value) {
        int val=get(key);
        if(val==-1){//不存在
            size++;
            Node node=new Node(key,value);
            addToHead(node);
            map.put(key,node);
            //空间不够
            if(size>capacity){
                Node no=deleteTail();
                map.remove(no.key);//从缓存中删除
                size--;
            }
        }
        else{//存在
            Node node=map.get(key);
            node.val=value;
            map.put(key,node);
            moveToHead(node);
        }
    }
    //删除节点
    public void delete(Node node){
        node.prev.next=node.next;
        node.next.prev=node.prev;
    }
    //删除尾部
    public Node deleteTail(){
        Node res=tail.prev;
        delete(res);
        return res;
    }
    //加到头部
    public void addToHead(Node node){
        node.next=head.next;
        node.next.prev=node;
        head.next=node;
        node.prev=head;
    }
    //移到头部
    public void moveToHead(Node node){
        delete(node);
        addToHead(node);
    }
}

复杂度

时间复杂度:对于 put 和 get 都是O(1)。

空间复杂度:O(capacity),因为哈希表和双向链表最多存储capacity+1 个元素。

结果

【刷题1】LeetCode 146. LRU缓存机制 java题解_第2张图片

你可能感兴趣的:(LeetCode,链表,java,哈希表,leetcode)