要件: LRU (Least Recent Used) キャッシュ制約を満たすデータ構造を設計および実装してください。
get 関数と put 関数は、平均時間計算量 O(1) で実行する必要があります。
アイデア:辞書 + 二重リンクリストを
使用する図:
迅速:
public class Solution {
class Node {
//需要存储key 移除key-value需要 key
var key: Int
var value: Int
var left: Node?
var right: Node?
init(key :Int=0, value: Int=0, left: Node?=nil, right: Node?=nil) {
self.key = key
self.value = value
self.left = left
self.right = right
}
}
private var dic = Dictionary<Int, Node>.init()
private var capacity = 0
private var headNode = Node.init(key: -1, value: -1, left: nil, right: nil)
private var tailNode = Node.init(key: -1, value: -1, left: nil, right: nil)
init(_ capacity: Int) {
self.capacity = capacity
self.headNode.right = self.tailNode
self.tailNode.left = self.headNode
}
func get(_ key: Int) -> Int {
if !self.dic.keys.contains(key){
return -1
}else{
self.swapNode(self.dic[key]!)
return self.dic[key]!.value
}
}
func set(_ key: Int, _ value: Int) {
if !self.dic.keys.contains(key){
let node = Node.init(key: key, value: value, left: nil, right: nil)
if self.dic.count < self.capacity {
self.addNodeToFirst(node)
self.dic.updateValue(node, forKey: key)
}else{
self.addNodeToFirst(node)
self.dic.updateValue(node, forKey: key)
//移除最久未使用(重要)
self.dic.removeValue(forKey: self.tailNode.left!.key)
self.removeNode(self.tailNode.left!)
}
}else{
let node = self.dic[key]!
node.value = value
self.swapNode(node)
}
}
private func swapNode(_ node: Node) {
if node.left!.value != -1{
//移除先前节点
self.removeNode(node)
//插入节点
self.addNodeToFirst(node)
}
}
private func addNodeToFirst(_ node: Node) {
node.right = self.headNode.right
self.headNode.right!.left = node
self.headNode.right = node
node.left = self.headNode
}
private func removeNode(_ node: Node) {
node.left!.right = node.right
node.right!.left = node.left
}
}