146. LRU Cache
Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations:
get and put.get(key) - Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1.put(key, value) - Set or insert the value if the key is not already present. When the cache reached its capacity, it should invalidate the least recently used item before inserting a new item.
Follow up:
Could you do both operations in O(1) time complexity?
Could you do both operations in O(1) time complexity?
Example:
LRUCache cache = new LRUCache( 2 /* capacity */ ); cache.put(1, 1); cache.put(2, 2); cache.get(1); // returns 1 cache.put(3, 3); // evicts key 2 cache.get(2); // returns -1 (not found) cache.put(4, 4); // evicts key 1 cache.get(1); // returns -1 (not found) cache.get(3); // returns 3 cache.get(4); // returns 4Solution:
hash map make the time of get() to O(1), doubleLinkedList make the node removal/add O(1).
1. Each time get/set put the access/new node to the head of the list.
remove(node);
moveToHead(node);
2. in set function, when the element is not in map and count larger than or equal the capacity, remove the least recently used element(LRU-remove the tail).don't forget to remove the node from map.
public class Ex146LRUCache {
//https://www.geeksforgeeks.org/design-a-data-structure-for-lru-cache/
//https://www.geeksforgeeks.org/design-a-data-structure-for-lru-cache/
/*
* linkedList不行吗,为什么一定要doublelinkedlist
* 删除o(1)
*/
public class DoubleLinkedNode{
public DoubleLinkedNode pre, next;
public int value;
public int key;
public DoubleLinkedNode(int key,int value){
this.value = value;
this.key = key;
}
}
public DoubleLinkedNode head, tail;
public HashMap<Integer,DoubleLinkedNode> map;
public int capacity;
public int count = 0;
public Ex146LRUCache(int capacity) {
head = new DoubleLinkedNode(0,0);
tail = new DoubleLinkedNode(0,0);
map = new HashMap<Integer,DoubleLinkedNode>();
head.next = tail;
tail.pre = head;
this.capacity = capacity;
}
public int get(int key) {
if(map.containsKey(key)){
DoubleLinkedNode node = map.get(key);
remove(node);
moveToHead(node);
return node.value;
}else{
return -1;
}
}
public void put(int key, int value) {
if(map.containsKey(key)){
DoubleLinkedNode node = map.get(key);
node.value = value;
remove(node);
moveToHead(node);
}else{
DoubleLinkedNode node = new DoubleLinkedNode(key,value);
map.put(key, node);//important
if(count >= capacity){
map.remove(this.tail.pre.key);//delete map before remove the element from linkedList
removeTail();
moveToHead(node);
}else{
moveToHead(node);
}
count++;
}
}
private void remove(DoubleLinkedNode node){
DoubleLinkedNode pre = node.pre;
DoubleLinkedNode next = node.next;
pre.next = next;
next.pre = pre;
}
private void removeTail(){
DoubleLinkedNode last = this.tail.pre;
DoubleLinkedNode lastPre = last.pre;
lastPre.next = this.tail;
this.tail.pre = lastPre;
}
private void moveToHead(DoubleLinkedNode node){
DoubleLinkedNode first = this.head.next;
first.pre = node;
node.next = first;
this.head.next = node;
node.pre = this.head;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
// case 1
// Ex146LRUCache cache = new Ex146LRUCache(2);
// cache.put(1, 1);
// cache.put(2, 2);
// System.out.println(cache.get(1));
// cache.put(3, 3);
// System.out.println(cache.get(2));
// cache.put(4, 4);
// System.out.println(cache.get(1));
// System.out.println(cache.get(3));
// System.out.println(cache.get(4));
// case 2
Ex146LRUCache cache = new Ex146LRUCache(1);
cache.put(2, 1);
System.out.println(cache.get(2));
//["LRUCache","put","put","get","put","get","put","get","get","get"]
//[[2],[1,1],[2,2],[1],[3,3],[2],[4,4],[1],[3],[4]]
}
Comments
Post a Comment