題目連接:https://leetcode.com/problems...node
這個題要求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能夠作的。web
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); */
題目連接:https://leetcode.com/problems...數據結構
上一題是隻考慮出現的時間,這題加了frequency。那麼再加一個map存freq應該是可行的。如今node除了要保存順序還得保存freq,感受上像是個二維的,先按freq排序再考慮出現順序。每次得保存下這個freq出現最先的值,再出現的時候,要從這freq裏刪了,移到下一個freq的tail上。想了下感受仍是不太好作,看了網上的答案。
參考這個博客:
http://bookshadow.com/weblog/...app
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):this
case 1: return -1code
case 2: exist =>blog
find keyNode and remove from freqNode, if cur freqNode has no element, remove freqNode排序
find freqNode through freqMap,ci
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); */