LRU Cache
题目链接:https://leetcode.com/problems...
这个题要求O(1)的复杂度。首先要做到get(key)是O(1),能想到的数据结构只有两三种,一个是HashMap<key, value>,一个是List<value>,key是index,还有一个Array[value], key是index。array不太可能,因为长度要initial而且不可变,题目也没说长度固定。list也不行,因为有put操作,list的insert操作是O(N)的。hashmap可以做到get和put都是O(1)。因为还有put函数,要可以remove least recently used cache,所以还需要一个数据结构来记录顺序,自然想到list。set以及delete操作在LinkedList里面都是O(1),就是要找到已存在的key这个操作在list是O(N),因为即要删除least recently的,也要加most recently的,所以是个double linked list。可以把map里面的value信息改成key在list里面该key对应的list node,然后在list里面存value信息。这其实也就是LinkedHashMap可以做的。
public class LRUCache {
class ListNode {
ListNode prev;
ListNode next;
int val = 0;
int key = 0;
ListNode() {}
ListNode(int key, int val) {
this.key = key;
this.val = val;
}
}
// new node(most recently) add to the tail part
public void append(ListNode node) {
node.prev = tail.prev;
tail.prev.next = node;
node.next = tail;
tail.prev = node;
}
// least recently node need to be remove from head
public void remove() {
remove(head.next);
}
// remove the certain node
public void remove(ListNode node) {
node.prev.next = node.next;
node.next.prev = node.prev;
}
ListNode head, tail;
Map<Integer, ListNode> map;
int remain;
public LRUCache(int capacity) {
remain = capacity;
// map for get
map = new HashMap();
// list for put
head = new ListNode();
tail = new ListNode();
head.next = tail;
tail.prev = head;
}
public int get(int key) {
if(map.containsKey(key)) {
// remove the key node to the tail
int value = map.get(key).val;
put(key, value);
return value;
}
else return -1;
}
public void put(int key, int value) {
if(map.containsKey(key)) {
ListNode node = map.get(key);
node.val = value;
remove(node);
append(node);
}
else {
// not contain, check if count > capacity
// remove the least recent node in list & map
if(remain == 0) {
map.remove(head.next.key);
remove();
remain++;
}
ListNode node = new ListNode(key, value);
append(node);
map.put(key, node);
remain--;
}
}
}
/**
* Your LRUCache object will be instantiated and called as such:
* LRUCache obj = new LRUCache(capacity);
* int param_1 = obj.get(key);
* obj.put(key,value);
*/
LFU Cache
题目链接:https://leetcode.com/problems...
上一题是只考虑出现的时间,这题加了frequency。那么再加一个map存freq应该是可行的。现在node除了要保存顺序还得保存freq,感觉上像是个二维的,先按freq排序再考虑出现顺序。每次得保存下这个freq出现最早的值,再出现的时候,要从这freq里删了,移到下一个freq的tail上。想了下感觉还是不太好做,看了网上的答案。
参考这个博客:
http://bookshadow.com/weblog/...
first -> point to the freqNode with freq = 1
Map<key, freqNode> freqMap
relation between freqNode:
first(freq 0) <-> freq 1 <-> freq 2 <-> ......
Map<key, keyNode> keyMap
get(key):
case 1: return -1
-
case 2: exist =>
find keyNode and remove from freqNode, if cur freqNode has no element, remove freqNode
find freqNode through freqMap,
find next freqNode(freq + 1) through freqNode,
add keyNode to the tail of next freqNode
put(key, value)
case 1: not exist in keyMap => add to the tail of freqNode with freq = 1
-
case 2: exist =>
find keyNode, set value and remove from freqNode, if cur freqNode has no element, remove freqNode
find freqNode through freqMap,
find next freqNode(freq + 1) through freqNode,
add keyNode to the tail of next freqNode
其中,keyNode和keyMap和上一题一样都是可以用LinkedHashMap来实现的。那么这里可以稍微改一下,把keyMap里面直接放<key, value>然后用一个LinkedHashSet来存所有有相同freq的keyNode,只需要存key即可。
public class LFUCache {
class freqNode {
int freq = 0;
freqNode prev, next;
// store keys
LinkedHashSet<Integer> keyNodes = new LinkedHashSet();
freqNode() {}
freqNode(int freq) { this.freq = freq; }
public int delete() {
// if(keyNodes.isEmpty()) return;
int key = keyNodes.iterator().next();
keyNodes.remove(key);
return key;
}
public void delete(int key) {
// if(!keyNodes.contains(key)) return;
keyNodes.remove(key);
}
public void append(int key) {
keyNodes.add(key);
}
}
int remain;
// key, freqNode pair
Map<Integer, freqNode> freqMap;
// key, value pair
Map<Integer, Integer> keyMap;
freqNode first;
freqNode last;
public LFUCache(int capacity) {
this.remain = capacity;
freqMap = new HashMap();
keyMap = new HashMap();
first = new freqNode();
last = new freqNode();
first.next = last;
last.next = first;
}
public int get(int key) {
if(!keyMap.containsKey(key)) return -1;
else {
updateFreq(key);
return keyMap.get(key);
}
}
public void put(int key, int value) {
if(!keyMap.containsKey(key)) {
if(remain == 0) {
if(first.next.freq == 0) return;
// remove the least frequent
int del = first.next.delete();
keyMap.remove(del);
freqMap.remove(del);
remain++;
}
// update map and add node
keyMap.put(key, value);
update(first, key);
remain--;
}
else {
updateFreq(key);
keyMap.put(key, value);
}
}
private void updateFreq(int key) {
freqNode node = freqMap.get(key);
update(node, key);
// remove current node if has no keyNodes
node.delete(key);
if(node.keyNodes.size() == 0) {
removeNode(node);
}
}
private void update(freqNode node, int key) {
// append to the next freq
addAfterNode(node);
node.next.append(key);
// update freqMap key with next freqNode
freqMap.put(key, node.next);
}
private void addAfterNode(freqNode node) {
if(node.next.freq != node.freq + 1) {
freqNode newNode = new freqNode(node.freq + 1);
freqNode temp = node.next;
node.next = newNode;
newNode.prev = node;
temp.prev = newNode;
newNode.next = temp;
node = null;
}
}
private void removeNode(freqNode node) {
node.prev.next = node.next;
node.next.prev = node.prev;
}
}
/**
* Your LFUCache object will be instantiated and called as such:
* LFUCache obj = new LFUCache(capacity);
* int param_1 = obj.get(key);
* obj.put(key,value);
*/
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。