【问题标题】:Print list unique items in order of their frequency of occurrence按出现频率的顺序打印列表唯一项目
【发布时间】:2017-08-15 22:20:28
【问题描述】:

假设我们有一个整数数组,甚至是连续的整数流。这个想法是根据出现频率以降序打印独特的元素。例如,对于 7, 4, 2, 4, 9, 6, 5, 6, 2, 0, 2, 1 我们应该得到: 2, 4, 6, 7, 9, 5, 0, 1 as 2 出现三个次,4 和 6 两次,其余的只是一次。

有没有比 (sorting map based by value) 计算元素的出现次数、将它们存储在 map 中然后根据 value 对 map 进行排序更好、更有效的方法?

【问题讨论】:

  • 什么编程语言?
  • 让我们假设它是 Java,但这更多的是找到一种有效的算法,而不是使用编程语言的能力和库,因为最终编程语言使用智能算法。
  • 显而易见的选择是您已经提到的排序映射,但根据您的大小,考虑使用完整的 RDBMS 并使用数据库索引的强大功能可能也是值得的数据也应该适用于值的流式列表,您不必担心内存映射等内存不足问题。

标签: algorithm sorting frequency find-occurrences


【解决方案1】:

专注于可能将输入作为整数流接受的问题,一种解决方案是修改插入排序...

创建一个列表列表(此处命名为countlist),最初为空。每次接受一个新值时,遍历countlist 中的每个列表,查找该值。如果您在countlist[i] 中找到值,请从其当前列表中删除该值并将其插入countlist[i+1],如有必要,将新列表添加到countlist。如果找不到值,请将值插入到countlist[1]

迭代降序而不是升序的目的是,如果您在countlist[i-1] 中找到该值,则它允许您维护一个指向countlist[i] 中插入值的位置的指针。如果您不需要对共享相同计数的值进行子排序,则可以跳过此指针并迭代升序。

我相信这个算法总体上是 O(n2)。处理每个新值的时间为 O(n),并且结果会随您进行排序。在任何时候,您都可以通过以降序遍历countlist 并打印每个列表来打印正确的顺序(到目前为止)。

示例运行,使用问题中的示例...

input: 7, 4, 2, 4, 9, 6, 5, 6, 2, 0, 2, 1

After accepting 7:
countlist[1] = 7

After accepting 4:
countlist[1] = 4, 7

After accepting 2:
countlist[1] = 2, 4, 7

After accepting 4:
countlist[1] = 2, 7
countlist[2] = 4

After accepting 9:
countlist[1] = 2, 7, 9
countlist[2] = 4

After accepting 6:
countlist[1] = 2, 6, 7, 9
countlist[2] = 4

After accepting 5:
countlist[1] = 2, 5, 6, 7, 9
countlist[2] = 4

After accepting 6:
countlist[1] = 2, 5, 7, 9
countlist[2] = 4, 6

After accepting 2:
countlist[1] = 5, 7, 9
countlist[2] = 2, 4, 6

After accepting 0:
countlist[1] = 0, 5, 7, 9
countlist[2] = 2, 4, 6

After accepting 2:
countlist[1] = 0, 5, 7, 9
countlist[2] = 4, 6
countlist[3] = 2

After accepting 1:
countlist[1] = 0, 1, 5, 7, 9
countlist[2] = 4, 6
countlist[3] = 2

【讨论】:

  • 有趣的方法,但我相信按值排序地图将是 O(nlogn),这比 O(n^2) 要好。
  • 同意。我专注于输入是整数流的情况(问题提到)。因此,我构建了算法,不需要知道我们将获得多少个值,也不需要在接受每个输入后“重新排序”。
【解决方案2】:

如果您使用的是 Python,请使用 collections.Counter 类及其 Counter.most_common() 方法

from collections import Counter
counted = Counter([7, 4, 2, 4, 9, 6, 5, 6, 2, 0, 2, 1])
ordered = [value for value, count in counted.most_common()]
print(ordered)  # [2, 4, 6, 0, 1, 5, 7, 9]

source 可用,显示在 most_common() 中使用的 heapq

【讨论】:

    【解决方案3】:

    但是,在我看来,应该有很多有效的算法来解决这个问题,因为可能有一种方法可以动态排序频率。

    这个问题实际上是代数树模型中的Omega(nlogn)(该模型下不允许散列),从Element Distinctness Problem减少,所以如果你希望得到一个(或常数)迭代来解决它,而无需任何辅助数据结构来解决它 - 这是不可能的,因为它允许我们在代数树模型中解决 O(n) 中的元素区别。

    这类问题的典型解决方案是:

    1. (您的建议):构建地图,删除重复项并按频率排序
    2. 类似于 1,但不是映射 - 对项目进行排序,使用二分搜索很容易找到每个元素重复的次数。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-06-24
      • 1970-01-01
      • 1970-01-01
      • 2012-05-20
      • 2020-02-06
      • 2014-06-19
      • 1970-01-01
      相关资源
      最近更新 更多