package com.heu.wsq.niuke.top200;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 设计LRU缓存结构
* @author wsq
* @date 2021/5/8
* 设计LRU缓存结构,该结构在构造时确定大小,假设大小为K,并有如下两个功能
* set(key, value):将记录(key, value)插入该结构
* get(key):返回key对应的value值
* [要求]
* set和get方法的时间复杂度为O(1)
* 某个key的set或get操作一旦发生,认为这个key的记录成了最常使用的。 当缓存的大小超过K时,移除最不经常使用的记录,即set或get最久远的。
* 若opt=1,接下来两个整数x, y,表示set(x, y)
* 若opt=2,接下来一个整数x,表示get(x),若x未出现过或已被移除,则返回-1
* 对于每个操作2,输出一个答案
*
* 示例1:
* 输入
* [[1,1,1],[1,2,2],[1,3,2],[2,1],[1,4,4],[2,2]],3
* 输出
* [1,-1]
*/
public class LRU {
public int[] LRU (int[][] operators, int k) {
// write code here
List<Integer> list = new ArrayList<>();
LRUCache lruCache = new LRUCache(k);
for(int[] op: operators){
if(op[0] == 1){
lruCache.set(op[1], op[2]);
}else if(op[0] == 2){
list.add(lruCache.get(op[1]));
}
}
int[] ans = new int[list.size()];
for(int i = 0; i < list.size(); i++){
ans[i] = list.get(i);
}
return ans;
}
}
class LRUCache{
/**
* 双向链表
*/
class LinkedNode{
private int key;
private int value;
private LinkedNode prev;
private LinkedNode next;
public LinkedNode(){}
public LinkedNode(int key, int value){
this.key = key;
this.value = value;
}
}
/**
* 保存头尾节点的指针,以便于在O(1)时间内进行去除链表尾,和新增节点到链表头
*/
private LinkedNode head;
private LinkedNode tail;
/**
* 保存key与node的映射,作为缓存表
*/
private Map<Integer, LinkedNode> cache;
/**
* 定义缓存表的容量
*/
private int capacity;
public LRUCache(int k){
this.cache = new HashMap<>();
this.capacity = k;
this.head = new LinkedNode();
this.tail = new LinkedNode();
this.head.next = this.tail;
this.tail.prev = this.head;
}
/**
* 添加节点到缓存中
* 1.当缓存中没有对应的记录信息,则新建一个节点保存到缓存中,并将对应的节点放置到链表的头部
* 2.当缓存中有对应的记录信息,更新记录节点的value,,并将该记录节点更新到链表的头部,表示该记录最近被使用
* @param k
* @param v
*/
public void set(int k, int v){
LinkedNode node = this.cache.get(k);
if(node == null){
node = new LinkedNode(k, v);
this.cache.put(k, node);
addToHead(node);
if(this.cache.size() > this.capacity){
LinkedNode tailNode = rmTailNode();
this.cache.remove(tailNode.key);
}
}else{
node.value = v;
rmNodeToHead(node);
}
}
/**
* 通过key获取缓存信息
* 并且需要更新该记录到链表的头部,表示该缓存记录最近被使用了
* @param k
* @return
*/
public int get(int k){
LinkedNode node = this.cache.get(k);
if(node != null){
rmNodeToHead(node);
}
return node == null ? -1 :node.value;
}
private void rmNodeToHead(LinkedNode node){
rmNode(node);
addToHead(node);
}
private void rmNode(LinkedNode node){
node.prev.next = node.next;
node.next.prev = node.prev;
}
private void addToHead(LinkedNode node){
node.next = this.head.next;
this.head.next = node;
node.prev = this.head;
node.next.prev = node;
}
private LinkedNode rmTailNode(){
LinkedNode node = this.tail.prev;
rmNode(node);
return node;
}
}
设计LRU缓存结构
最新推荐文章于 2024-08-27 17:03:36 发布