Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations: get
and set
.
get(key)
- Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1.
set(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.
思路: 1. Using LinkedHashMap to implement the LRU.
One is using LinkedHashMap order, the other is do it by yourself
思路2: Only using doubly LinkedList. Every time, we insert the latest using element into the head, and remove it from the list if it existed. If the size == capacity, we need to remove the tail element.
易错点:注意不论是get(int key) 还是 put (int key, int value) 都千万别忘记删除老的, 插入新的。
import java.util.LinkedHashMap;
public class LRUCache {
int capacity;
LinkedHashMap<Integer, Integer> map;
public LRUCache(int capacity) {
this.capacity = capacity;
map = new LinkedHashMap<Integer, Integer>(capacity, 0.75f, true);
}
public int get(int key) {
if(map.containsKey(key)){
return map.get(key);
}else{
return -1;
}
}
public void set(int key, int value) {
if(map.containsKey(key)){
map.put(key, value);
}else{
if(map.size() == capacity){
int oldKey = map.keySet().iterator().next();
map.remove(oldKey);
}
map.put(key, value);
}
}
}
import java.util.LinkedHashMap;
public class LRUCache {
int capacity;
LinkedHashMap<Integer, Integer> map;
public LRUCache(int capacity) {
this.capacity = capacity;
map = new LinkedHashMap<Integer, Integer>();
}
public int get(int key) {
if(map.containsKey(key)){
int val = map.get(key);
map.remove(key);
map.put(key, val);
return val;
}
return -1;
}
public void set(int key, int value) {
if(map.containsKey(key)){
map.remove(key);
map.put(key, value);
}else{
if(map.size() == capacity){
int oldKey = map.keySet().iterator().next();
map.remove(oldKey);
}
map.put(key, value);
}
}
}
思路 2: 用一个双向链表来存储每个节点的位置, 这样可以做到在 o(1) 时间内删除和添加。
易错点: 注意更新插入到头的时候, pre节点要置为空。
public class LRUCache {
class ListNode{
int key;
int val;
public ListNode pre = null;
public ListNode next = null;
public ListNode(int key, int val){
this.key = key;
this.val = val;
}
}
public int capacity = 0;
public int size;
public ListNode head = null;
public ListNode end = null;
HashMap<Integer, ListNode> map = new HashMap<Integer, ListNode>();
public LRUCache(int capacity) {
this.capacity = capacity;
size = 0;
}
public int get(int key) {
if(map.containsKey(key)){
ListNode cur = map.get(key);
remove(cur);
insertHead(cur);
return cur.val;
}else{
return -1;
}
}
public void set(int key, int value) {
if(map.containsKey(key)){
ListNode cur = map.get(key);
remove(cur);
cur.val = value;
insertHead(cur);
}else{
if(size >= capacity){
map.remove(end.key);
end = end.pre;
if(end != null){
end.next = null;
}
size--;
}
ListNode cur = new ListNode(key, value);
map.put(key, cur);
insertHead(cur);
size++;
}
}
private void remove(ListNode cur){
ListNode pre = cur.pre;
ListNode post = cur.next;
if(pre == null){
head = post;
}else{
pre.next = post;
}
if(post == null){
end = pre;
}else{
post.pre = pre;
}
}
private void insertHead(ListNode cur){
cur.next = head;
cur.pre = null;//-----
if(head != null){
head.pre = cur;
}
head = cur;
if(end == null){
end = cur;
}
}
}