class Node {
public int key, val;
public Node next, prev;
public Node(int k, int v) {
this.key = k;
this.val = v;
}
}
class DoubleList {
private Node head, tail;
private int size;
public void addFirst(Node node) {
if (head == null) {
head = tail = node;
} else {
Node h = head;
h.prev = node;
node.next = h;
head = node;
}
size++;
}
public void remove(Node node) {
if (head == node && tail == node) {
head = null;
tail = null;
} else if (tail == node) {
node.prev.next = null;
tail = node.prev;
node.prev = null;
} else if (head == node) {
node.next.prev = null;
head = node.next;
node.next = null;
} else {
node.prev.next = node.next;
node.next.prev = node.prev;
node.next = null;
node.prev = null;
}
size--;
}
public Node removeLast() {
Node node = tail;
remove(tail);
return node;
}
public int size() {
return size;
}
}
class LRUCache {
private HashMap<Integer, Node> map;
private DoubleList doubleList;
private int cap;
public LRUCache(int capacity) {
this.cap = capacity;
map = new HashMap<>();
doubleList = new DoubleList();
}
public int get(int key) {
if (!map.containsKey(key))
return -1;
Node node = map.get(key);
int val = node.val;
doubleList.remove(node);
doubleList.addFirst(node);
return val;
}
public void put(int key, int val) {
Node x = new Node(key, val);
if (map.containsKey(key)) {
doubleList.remove(map.get(key));
} else {
if (cap == doubleList.size()) {
Node last = doubleList.removeLast();
map.remove(last.key);
}
}
doubleList.addFirst(x);
map.put(key, x);
}
}