我正在处理的问题需要在数组上处理多个查询(数组的大小小于10k
,最大的元素肯定小于10^9
)。
查询由两个整数组成,其中一个必须找到具有相同整数的子数组的总数。最多可能有5 * 10^5
次查询。
例如,给定数组[1, 2, 1]
和查询1 2
,我们发现有两个子数组具有相同的1
和2
计数,即{{1 }和[1, 2]
。
我最初的方法是使用动态编程来构建地图,例如[2, 1]
。我会以类似的方式使用它来使用前缀和,但是频率会累积。
构建此地图需要我memo[i][j] = the number of times the number i appears in the array, until index j
。对于每个查询,我会针对每个间隔执行O(n^2)
处理并递增答案。这导致O(1)
[O((q + 1)n * (n - 1) / 2))
是查询数量]的复杂性,也就是说q
,但我也想强调这个令人生畏的常数因素。
经过一些重新安排后,我试图找出是否有办法确定每个子阵列中每个元素的频率计数。我强烈地感觉到这个问题是关于细分树的问题,而且我一直在努力想出一个合适的模型,这是我唯一能想到的。
然而,考虑到组合节点拥有如此大量信息的复杂性,我的方法在这种情况下似乎并不太有用,更不用说内存开销了。
如何有效地解决这个问题?
答案 0 :(得分:1)
通过计算累积计数差异的频率计数,您可以将每个查询的时间从O(n ^ 2)减少到O(n):
from collections import defaultdict
def query(A,a,b):
t = 0
freq = defaultdict(int)
freq[0] = 1
for x in A:
if x==a:
t+=1
elif x==b:
t-=1
freq[t] += 1
return sum(count*(count-1)/2 for count in freq.values())
print query([1,2,1],1,2)
这个想法是t表示两个元素的计数之间的总差异。
如果我们在阵列中找到两个具有相同总差异的位置,我们可以得出结论,这些位置之间的子阵列必须具有相同的数字。
表达式count*(count-1)/2
只是计算从计数中选择具有相同差异的两个位置的方式的数量。
例如,假设我们有数组[1,1,1,2,2,2]。累积差异的值(1' s的数量为2')将为:
0,1,2,3,2,1,0
每对具有相同数字的对应于具有相同计数的子阵列。例如看着这对2,我们发现从位置2到位置4的范围具有相同的数量。
如果仍然不够快,您可以优化查询功能以快速跳过所有不等于a或b的元素。例如,您可以为包含该元素的所有位置的每个元素值准备一个列表。
获得此列表后,您可以立即跳转到a或b的下一个位置。对于所有中间值,我们知道差异不会改变,因此您可以通过跳过的元素的数量更新频率(而不是总是仅向计数添加1)。