Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations: get
and set
.
Copy LRUCache cache = new LRUCache( 2 ) ;
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 4
33
44
这里操作都需要是常数时间的,使用一个LinkedHashMap记录元素的键和值,同时使用一个HashMap,记录这个键和其之前的节点,方便进行移动操作,这个map注意一定要时刻更新。
Copy private int capacity, size;
private ListNode sentinel, tail;
private Map<Integer, ListNode> map;
Copy public class LRUCache {
class ListNode {
public int key , val;
public ListNode next;
public ListNode ( int key , int val) {
this . key = key;
this . val = val;
next = null ;
}
}
private int capacity , size;
private ListNode sentinel , tail;
private Map < Integer , ListNode > map; //key -> prev
/*
* @param capacity: An integer
*/
public LRUCache ( int capacity) {
// do intialization if necessary
this . capacity = capacity;
map = new HashMap <>();
sentinel = new ListNode( 0 , 0 ) ;
tail = sentinel;
}
private void moveToTail ( int key) {
ListNode prev = map . get (key);
ListNode curr = prev . next ;
if (tail == curr) {
return ;
}
prev . next = prev . next . next ; //delete
tail . next = curr; // add to tail
if ( prev . next != null ) { //is last?
map . put ( prev . next . key , prev);
}
map . put ( curr . key , tail);
tail = curr;
}
/*
* @param key: An integer
* @return: An integer
*/
public int get ( int key) {
// write your code here
if ( ! map . containsKey (key)) {
return - 1 ;
}
moveToTail(key) ;
return tail . val ;
}
public void set ( int key , int value) {
// write your code here
if ( get(key) != - 1 ) { //already exist
ListNode prev = map . get (key);
prev . next . val = value;
return ;
}
if (size < capacity) { // less than size add directly
size ++ ;
ListNode curr = new ListNode(key , value) ;
tail . next = curr;
map . put (key , tail);
tail = curr;
return ;
}
// third case: not exist and up to the cap -> remove least and add
ListNode first = sentinel . next ;
map . remove ( first . key );
first . key = key;
first . val = value;
map . put (key , sentinel);
moveToTail(key) ;
}
}