Leetcode:146. LRU缓存机制

Leetcode:146. LRU缓存机制

题目描述

运用你所掌握的数据结构,设计和实现一个  LRU (最近最少使用) 缓存机制。它应该支持以下操作: 获取数据 get 和 写入数据 put 。

获取数据 get(key) - 如果密钥 (key) 存在于缓存中,则获取密钥的值(总是正数),否则返回 -1。
写入数据 put(key, value) - 如果密钥已经存在,则变更其数据值;如果密钥不存在,则插入该组「密钥/数据值」。当缓存容量达到上限时,它应该在写入新数据之前删除最久未使用的数据值,从而为新的数据值留出空间。

 

进阶:

你是否可以在 O(1) 时间复杂度内完成这两种操作?

 

示例:

LRUCache cache = new LRUCache( 2 /* 缓存容量 */ );

cache.put(1, 1);
cache.put(2, 2);
cache.get(1); // 返回 1
cache.put(3, 3); // 该操作会使得密钥 2 作废
cache.get(2); // 返回 -1 (未找到)
cache.put(4, 4); // 该操作会使得密钥 1 作废
cache.get(1); // 返回 -1 (未找到)
cache.get(3); // 返回 3
cache.get(4); // 返回 4

思路

思路1 HashMap + 双向链表

因为要满足存取都是O(1)复杂度,且有容量限制(所以重点在于如何删除以及置于最前),所以可以使用一个HashMap和双向链表实现

代码

代码1

import java.util.Hashtable;
class LRUCache {

    class DNode{
        int key;
        int value;
        DNode pre;
        DNode next;
    }
    
    private void addNode(DNode node){
        node.pre = head;
        node.next = head.next;
        head.next.pre = node;
        head.next = node;
    }
    
    private void removeNode(DNode node){
        DNode pre = node.pre;
        DNode next = node.next;
        
        pre.next = next;
        next.pre = pre;
    }
    
    private void toHead(DNode node){
        removeNode(node);
        addNode(node);
    }
    
    private DNode removeTail(){
        DNode pre = tail.pre;
        removeNode(pre);
        return pre;
    }
    
    private DNode head, tail;
    private HashMap cache =
          new HashMap();
    int maxSize;
    int size;
    
    public LRUCache(int capacity) {
        this.maxSize = capacity;
        this.size = 0;
        this.head = new DNode();
        this.tail = new DNode();
        this.head.next = tail;
        this.tail.pre = head;
    }
    
    public int get(int key) {
        DNode node = cache.get(key);
        if (node == null){
            return -1;
        }else{
            toHead(node);
            return node.value;
        }
    }
    
    public void put(int key, int value) {
        DNode pre = cache.get(key);
        if (pre == null){
            pre = new DNode();
            pre.key = key;
            pre.value = value;
            this.size += 1;
            if (this.size > this.maxSize){
                DNode removeNode = removeTail();
                cache.remove(removeNode.key);
                this.size = this.maxSize;
            }
            addNode(pre);
            cache.put(key, pre);
        }else{
            pre.value = value;
            toHead(pre);
        }
    }
}

复杂度分析

思路1时间复杂度

$O(1)$

思路1空间复杂度

$O(1)$


文章作者: 小风雷
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 小风雷 !
评论
 上一篇
Leetcode:37. 解数独 Leetcode:37. 解数独
Leetcode: 37.解数独题目描述编写一个程序,通过已填充的空格来解决数独问题。 一个数独的解法需遵循如下规则: 数字 1-9 在每一行只能出现一次。 数字 1-9 在每一列只能出现一次。 数字 1-9 在每一个以粗实线分隔的 3
2020-06-06
下一篇 
Leetcode:134. 加油站 Leetcode:134. 加油站
[Leetcode: 134. 加油站]题目描述在一条环路上有 N 个加油站,其中第 i 个加油站有汽油 gas[i] 升。 你有一辆油箱容量无限的的汽车,从第 i 个加油站开往第 i+1 个加油站需要消耗汽油 cost[i] 升。你从其
2020-05-13
  目录