我有一个由几千个整数组成的日志文件,每个整数分隔成一个新行。我已将此解析为一组此类整数,也已排序。现在我的问题变成找到重要的"此日志中的整数 - 这些是显示一些用户可配置时间的部分。
例如,给定日志,用户可以过滤以仅查看显示特定次数的条目。
目前我正在扫描整个阵列并记录每个条目出现的次数。当然有更好的方法吗?
答案 0 :(得分:1)
您的排序可能需要O(NlogN)时间。您是否需要为同一数据集多次(n / I)查询?
如果是,请浏览已排序的数组,生成(Value;Count)
对并按Count
字段对其进行排序。现在,您可以使用二进制搜索轻松地将具有高计数的对分开
答案 1 :(得分:0)
首先,我需要注意以下只是理论上的解决方案,您可能应该使用@MBo提出的建议。
获取已排序数组的每个m = n / l
元素。只有那些元素才是重要的,因为m
和i*m
之间没有长度为(i+1)*m
的相同元素序列。
对于每个元素x
,使用二进制搜索查找数组的下限和上限。减去索引,您可以知道计数,并决定保留或放弃x
不重要。
总复杂度为O((n/m) * log n) = O(l * log n)
。对于大m
,它可以(渐近地)优于O(n)
。但是,要在实践中获得改进,您需要非常具体的情况:
数组是给你预分类的(否则只是使用计数排序,你会立即得到答案)
您可以在i
中访问数组中的O(1)
元素而无需读取整个数组。否则,再次使用哈希表进行计数排序。
让我们假设你有一个由排序的固定宽度整数 "data.bin"
组成的文件(它也可以用于变宽,但需要额外的努力)。然后在伪代码中,算法可能是这样的:
def find_all_important(l, n):
m = n / l
for i = m to l step m:
x = read_integer_at_offset("data.bin", i)
lower_bound = find_lower_bound(x, 0, i)
upper_bound = find_upper_bound(x, i, n)
if upper_bound - lower_bound >= m:
report(x)
def find_lower_bound(x, begin, end):
if end - begin == 0:
return begin
mid = (end + begin) / 2
x = read_integer_at_offset("data.bin", mid)
if mid < x:
return find_lower_bound(x, mid + 1, end)
else:
return find_lower_bound(x, begin, mid)
作为猜测,与现代硬件上的天真O(n)
相比,你不会获得任何显着的改进,除非你的文件非常大(数百MB)。当然,如果您的数据不适合RAM,那么它是可行的。但是,与优化一样,它可能值得测试。