一、演算法思路
LRUCache類有以下函式和變數:
- LRUCache(int capacity): capacity是當前物件能夠儲存的鍵值對(key,value)最大個數。
- int get(int key): 根據指定的key尋找value值,若沒有找到key就返回-1
- void put(int key, int value): 儲存一個新的鍵值對(key,value),如果key已經存在,就更新value,如果當前已達最大容量,就將最近最少使用的鍵值對替換。
- void show(): 檢視當前所有鍵值對資訊。(題目並沒有要求書寫這個函式,只是為了方便除錯)。
- int size: 當前所儲存的鍵值對個數。
- int max_size: 最大鍵值對個數(對應建構函式的capacity)。
- Node *list:鍵值對陣列。
Node結構體的定義:
typedef struct LRUCacheNode { int key; int value; int count; } Node;
其中key,value構成了鍵值對(key,value),count表示已有多久沒有使用。當一個鍵值對節點(Node)被第一次插入、查詢或是修改,其count都會被置零,而其他節點的count自增。已達到最大儲存量後,插入節點會修改所有節點中count最大的,修改完畢(也就是value值被更新後),count會被置零,而其他節點的count依然會自增。
二、程式碼演示
LRUCache(int capacity) { max_size = capacity; size = 0; list = new Node[max_size]; }
LRUCache的建構函式僅僅初始化max_size,size和list。三者的定義如下:
private: int size; int max_size; Node *list;
接下來是get函式,比較簡單,依次遍歷list並尋找符合要求的節點,不要忘記將符合要求的節點的count置零,以及將其他節點的count自增:
int get(int key) { int value = -1; for (int i = 0; i < size; ++i) { Node *tmp = &list[i]; if (tmp->key == key) { tmp->count = 0; value = tmp->value; } else { tmp->count++; } } return value; }
接下來說重點——put函式:
void put(int key, int value) { bool contains = false; for (int i = 0; i < size; ++i) { Node *tmp = &list[i]; if (tmp->key == key) { tmp->count = 0; tmp->value = value; contains = true; } else { tmp->count++; } } if (contains) { return; } if (size >= max_size) { int max_count = -1; Node *max_node; for (int i = 0; i < size; ++i) { Node *tmp = &list[i]; if (tmp->count > max_count) { max_count = tmp->count; max_node = tmp; } } max_node->key = key; max_node->value = value; max_node->count = 0; } else { Node n; n.key = key; n.value = value; n.count = 0; list[size++] = n; } }
put函式首先在list中尋找(key,value)是否存在,是則僅更新節點並返回。如果沒有找到節點,接下來判斷list是否已滿:如果沒有滿,就將(key,value)儲存到list陣列;如果已經滿了,首先根據count大小,尋找出count最大的節點,將其修改(此步並不需要將其他節點count自增,因為在第一步尋找(key,value)是否存在是已經自增過了)。
接下來是show函式,可以自行調整樣式:
void show() { for (int i = 0; i < size; ++i) { Node *tmp = &list[i]; cout << tmp->key << "\t" << tmp->value << "\t" << tmp->count << "\n"; } }
main函式除錯:
int main() { LRUCache cache = LRUCache(2 /* 快取容量 */ ); cache.put(1, 1); cache.put(2, 2); cout << cache.get(1) << "\n"; // 返回 1 cache.put(3, 3); // 該操作會使得金鑰 2 作廢 cout << cache.get(2) << "\n"; // 返回 -1 (未找到) cache.put(4, 4); // 該操作會使得金鑰 1 作廢 cout << cache.get(1) << "\n"; // 返回 -1 (未找到) cout << cache.get(3) << "\n"; // 返回 3 cout << cache.get(4) << "\n"; // 返回 4 return 0; }
main函式輸出:
1 -1 -1 3 4
三、提交結果
執行用時並不理想,有待優化。