java - 确定在 O(n) 时间和 O(1) 空间内出现次数最多的元素

标签 java c algorithm

首先让我声明这不是作业问题。我正在尝试设计一个缓存,其逐出策略取决于缓存中出现次数最多的条目。在软件方面,假设我们有一个包含不同元素的数组,我们只想找到出现次数最多的元素。例如:{1,2,2,5,7,3,2,3} 应该返回 2。由于我使用的是硬件,简单的 O(n^2) 解决方案将需要巨大的硬件开销。使用哈希表的更聪明的解决方案适用于软件,因为哈希表的大小可以改变,但在硬件中,我将有一个固定大小的哈希表,可能不会那么大,所以冲突会导致错误的决定。我的问题是,在软件中,我们能否在O(n) 时间复杂度和O(1) 空间内解决上述问题?

最佳答案

不可能有O(n) 时间,O(1) 空间的解决方案,至少对于一般情况是这样。

作为amit points out ,通过解决这个问题,我们找到了 element distinctness problem 的解决方案(确定列表中的所有元素是否不同)已被证明在不使用元素索引计算机内存时花费 Θ(n log n) 时间。如果我们要使用元素来索引计算机的内存,给定一个无限范围的值,这至少需要 Θ(n) 空间。考虑到将这个问题简化为那个问题,那个问题的界限对这个问题强制执行相同的界限。

但是,实际上,如果除了通常用于存储每个元素的类型具有固定大小(例如 32 位整数)之外没有其他原因,范围将主要是有界的。如果是这种情况,这将允许 O(n) 时间,O(1) 空间解决方案,尽管由于涉及大常数因子(因为时间和空间复杂度将取决于值的范围)。

2个选项:

  • Counting sort

    Keeping an array of the number of occurrences of each element (the array index being the element), outputting the most frequent.

    如果您有一个有限范围的值,这种方法将是 O(1) 空间(和 O(n) 时间)。但从技术上讲,哈希表方法也是如此,因此这里的常数因子可能太大而无法接受。

    相关选项是radix sort (有一个就地变体,类似于快速排序)和 bucket sort .

  • Quicksort

    Repeatedly partitioning the data based on a selected pivot (through swapping) and recursing on the partitions.

    排序后我们可以遍历数组,跟踪连续元素的最大数量。

    这将花费 O(n log n) 时间和 O(1) 空间。

关于java - 确定在 O(n) 时间和 O(1) 空间内出现次数最多的元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23261128/

相关文章:

java - TreeMap 操作的时间复杂度- subMap, headMap, tailMap

c - 将带有 typedef 的结构数组传递给函数

algorithm - 使用预言机有效地对整数进行质因数分解

java - Log4j 创建 "target"文件夹,其中包含空的 "camel-spring-redis-test.log"日志文件

java - 使用mvn idea时无法加载intellij模块:idea

java - JUnit&Mockito : how to inject field values to Spring component?

C VS2010 - 堆损坏释放结构上的指针数组

c - 围栏密码算法c

c++ - 从二叉搜索树中删除节点

algorithm - 将两个列表与元素之间的最小距离组合起来