【发布时间】:2018-05-28 03:28:24
【问题描述】:
我在 Coursera 上攻读 Algorithms, Part I 课程,其中一个面试问题(未评分)如下:
十进制占优。给定一个有 n 个键的数组,设计一个算法来找出所有出现超过 n/10 次的值。预期的 算法的运行时间应该是线性的。
它有一个提示:
使用快速选择确定第 (n/10) 个最大的键并检查它是否 出现 n/10 次以上。
我不明白 n/10 最大键与 n/10 重复值有什么关系。它不会告诉我哪些值出现的次数超过 n/10 次。
有一个paper 为 n/k 找到了更通用的解决方案,但我很难理解论文中的代码。
解决此问题的一种方法是对输入数组进行排序,然后再计算每个不同值的出现次数。这将花费 O(nlogn) + O(n) 时间,这比问题所要求的要多。
想法?
【问题讨论】:
-
当提示指的是线性时,意味着您正在对数组进行一次索引。如果您要从最大到最小对数组进行排序,则需要 N^2。数组中的每个数字可能有重复项。数组中的每个唯一数字都是键。所以这个问题意味着你有一个字典(一个带有键的数组),你需要在字典中搜索超过 10 个项目的键。
-
@jdweng 课程中还没有引入字典或者哈希表,所以不能使用这样的数据结构。此外,正如我在问题中所说,有比 n^2 更快的排序算法可用。
-
你是对的。小数占优是 QuickSelect 之后的下一个候选对象:
n/10, 2*n/10..9*n/10,因此仅检查 n/10 是不够的 -
@MBo 请详细说明,没有关注。
-
如果一个元素出现超过 n/k 次,那么对于排序数组中 0 到 n/k 范围内的某些 i,它必须位于位置 i*n/k。 (如果它不在这些位置中的任何一个,则不可能有 n/k 个元素的副本,因为在两个连续的测试位置之间没有 n/k 个副本的空间。)快速选择可以在 O(n ),因此找到所有这些需要 O(kn),如果 K 是已知常数,则为 O(n)。但是通用的Boyer-Moore majority algorithm 可能更快更容易编码。
标签: arrays algorithm data-structures