携手创造,共同生长!这是我参加「日新计划 8 月更文应战」的第11天,点击检查活动详情

前语

本题为 LeetCode 前 100 高频题

咱们社区连续会将顾毅(Netflix 增加黑客,《iOS 面试之道》作者,ACE 工作健身教练。)的 Swift 算法题题解收拾为文字版以便利咱们学习与阅览。

LeetCode 算法到目前咱们已经更新到 145 期,咱们会保持更新时刻和进度(周一、周三、周五早上 9:00 发布),每期的内容不多,咱们希望咱们能够在上班路上阅览,长久积累会有很大提高。

不积跬步,无以至千里;不积小流,无以成江海,Swift社区 伴你前行。假如咱们有建议和定见欢迎在文末留言,咱们会极力满足咱们的需求。

难度水平:中等

1. 描绘

请你规划并实现一个满足 LRU (最近最少运用) 缓存 束缚的数据结构。

实现 LRUCache 类:

  • LRUCache(int capacity)正整数 作为容量 capacity 初始化 LRU 缓存
  • int get(int key) 假如关键字 key 存在于缓存中,则回来关键字的值,否则回来 -1
  • void put(int key, int value) 假如关键字 key 已经存在,则变更其数据值 value ;假如不存在,则向缓存中刺进该组 key-value 。假如刺进操作导致关键字数量超越 capacity ,则应该 逐出 最久未运用的关键字。

函数 getput 必须以 O(1) 的均匀时刻复杂度运转。

2. 示例

示例 1

输入
["LRUCache", "put", "put", "get", "put", "get", "put", "get", "get", "get"]
[[2], [1, 1], [2, 2], [1], [3, 3], [2], [4, 4], [1], [3], [4]]
输出
[null, null, null, 1, null, -1, null, -1, 3, 4]
解释
LRUCache lRUCache = new LRUCache(2);
lRUCache.put(1, 1); // 缓存是 {1=1}
lRUCache.put(2, 2); // 缓存是 {1=1, 2=2}
lRUCache.get(1);    // 回来 1
lRUCache.put(3, 3); // 该操作会使得关键字 2 报废,缓存是 {1=1, 3=3}
lRUCache.get(2);    // 回来 -1 (未找到)
lRUCache.put(4, 4); // 该操作会使得关键字 1 报废,缓存是 {4=4, 3=3}
lRUCache.get(1);    // 回来 -1 (未找到)
lRUCache.get(3);    // 回来 3
lRUCache.get(4);    // 回来 4

束缚条件:

  • 1 <= capacity <= 3000
  • 0 <= key <= 10000
  • 0 <= value <= 10^5
  • 最多调用 2 * 10^5getput

3. 答案

class LRUCache {
    private let capacity: Int
    private var count = 0
    private let head = LRUCacheNode(0, 0)
    private let tail = LRUCacheNode(0, 0)
    private var dict = [Int: LRUCacheNode]()
    init(_ capacity: Int) {
        self.capacity = capacity
        head.next = tail
        tail.pre = head
    }
    func get(_ key: Int) -> Int {
        if let node = dict[key] {
            remove(key)
            insert(node)
            return node.val
        }
        return -1
    }
    func put(_ key: Int, _ value: Int) {
        if let node = dict[key] {
            node.val = value
            remove(key)
            insert(node)
            return
        }
        let node = LRUCacheNode(key, value)
        dict[key] = node
        if count == capacity, let tailKey = tail.pre?.key {
            remove(tailKey)
        }
        insert(node)
    }
    private func insert(_ node: LRUCacheNode) {
        dict[node.key] = node
        node.next = head.next
        head.next?.pre = node
        node.pre = head
        head.next = node
        count += 1
    }
    private func remove(_ key: Int) {
        guard count > 0, let node = dict[key] else {
            return
        }
        dict[key] = nil
        node.pre?.next = node.next
        node.next?.pre = node.pre
        node.pre = nil
        node.next = nil
        count -= 1
    }
}
fileprivate class LRUCacheNode {
    let key: Int
    var val: Int
    var pre: LRUCacheNode?
    var next: LRUCacheNode?
    init(_ key: Int, _ val: Int) {
        self.key = key
        self.val = val
    }
}
  • 主要思想:运用链表和哈希映射来构建缓存。
  • 时刻复杂度: O(1)
  • 空间复杂度: O(k)

该算法题解的库房:LeetCode-Swift

点击前往 LeetCode 练习

关于咱们

咱们是由 Swift 爱好者共同保护,咱们会分享以 Swift 实战、SwiftUI、Swift 基础为中心的技术内容,也收拾收集优秀的学习材料。

后续还会翻译大量材料到咱们大众号,有感兴趣的朋友,能够加入咱们。