【问题标题】:LFU cache, how is get and set in O(1)?LFU 缓存,如何在 O(1) 中获取和设置?
【发布时间】:2018-08-12 08:02:19
【问题描述】:

在准备面试时,我遇到了一些问题,这让我质疑我对大 O 常数时间算法的理解。

LeetCode 上的一个问题要求创建 LFU 缓存问题的解决方案。

有3种方法可以实现:

构造函数 - 输入:整数容量

得到 - 输入:int 键 - 输出:int

设置 - 输入:int 键,int 值

容量表示您一次可以保存的缓存键/值对的最大数量。当容量被破坏时,您必须弹出访问频率最低的对。

显然,您必须跟踪每个项目的访问次数。

在问题的底部,它询问您是否可以在 O(1) 时间内获取和设置。

我正在研究这方面的多个提议的实现,很多人都同意它们是恒定时间实现的示例,但在我看来,它们看起来像 O(N)。

有关完整示例,请参见此处: https://leetcode.com/problems/lfu-cache/discuss/94515/Java-O(1)-Accept-Solution-Using-HashMap-DoubleLinkedList-and-LinkedHashSet?page=1

但是这个例子中的相关方法在下面的代码块中。注意 valueHash 和 nodeHash 都是 java 哈希表。

public int get(int key) {
    if (valueHash.containsKey(key)) {
        increaseCount(key);
        return valueHash.get(key);
    }
    return -1;
}

    public void set(int key, int value) {
    if ( cap == 0 ) return;
    if (valueHash.containsKey(key)) {
        valueHash.put(key, value);
    } else {
        if (valueHash.size() < cap) {
            valueHash.put(key, value);
        } else {
            removeOld();
            valueHash.put(key, value);
        }
        addToHead(key);
    }
    increaseCount(key);
}

方法调用Hashtable.containsKey和Hashtable.get,实现线性搜索。所以最坏情况的时间复杂度是 O(N) 对吧?我错过了什么?

【问题讨论】:

  • 我想这里的相关问题是:n是什么?
  • Hashtable 和 HashMap 是基于 hasing 的,containsKey()get() 是 O(1),由数组支持,如果发生冲突,元素会在数组的索引处链接。使用 Hasing 算法,将 key 转换为表示数组中索引的 int。访问数组中索引处的元素是 O(1)

标签: algorithm big-o constant-time


【解决方案1】:

无论您使用什么数据结构,它都有一些 悲观 的搜索时间 T(n),这取决于存储的项目数 n。如果您设置了一些最大容量 Nmax,并在程序执行期间保持它恒定,如问题陈述中特别要求的那样,那么处理任何请求的最长时间为 T(Nmax),即是恒定的。

感谢 @Zabuza 强调 Nmax 的恒定性。

【讨论】:

  • 为了扩展答案,这仅适用于Nmax 确实是一个常量,这意味着它不依赖于n。所以像Nmax = 10 * n 这样的东西不会是常数。
  • 谢谢。这很有意义。这是一种信心动摇。
  • 在这种情况下,容量由构造函数设置并且不能更改,但是是的,如果实现与这种情况下的问题所要求的略有不同,则必须考虑.
  • @Zabuza 我懒得强调这一点,因为它是问题定义的一部分('容量代表你一次可以保存的缓存键/值对的最大数量')。但是你指出来是对的;这是一个至关重要的要求,这会导致反直觉的结果。
猜你喜欢
  • 2019-04-01
  • 2010-10-31
  • 1970-01-01
  • 1970-01-01
  • 2017-11-19
  • 2023-04-07
  • 2020-03-16
  • 2016-11-11
  • 1970-01-01
相关资源
最近更新 更多