高效查询整数数组中范围的相等性

时间:2017-06-05 20:11:43

标签: algorithm performance time

给定一个大小为n的正整数数组,预计会发现两个范围是否相同,因为查询是否相等。如果范围1中存在的所有元素都存在于范围2中并且也在相同的计数中,则认为两个范围相等。

示例:

1 2 5 3 5 1 2

查询:

[1,3] and [5,7]
[2,4] and [3,5]

数目:

Yes
No

可以通过以下方式提出一个天真的解决方案:
1.对于每个查询,请制作存储每个范围O(n)的数组的两个副本 然后对每一个进行排序。 O(n*logn)
3.然后逐个元素比较并返回truefalseO(n)

因此,解决方案的复杂性为O(q*n*logn),其中q是查询的数量。是否有可能有效地解决这个问题?

PS:所有变量nq和数组元素的约束为<=10^5

2 个答案:

答案 0 :(得分:1)

虽然也可能有其他方法来解决这个问题,但是下面的方法可以很好地解决这个问题,在O(N)中。 (如果查询到达的次数为x次,则可以通过缓存查询结果来优化O(xN),只查询查询范围及其结果)

为了便于我们,请将查询中的起始和结束元素命名为 range1StartIndexrange2StartIndexrange1EndIndexrange2EndIndex

  1. 看两个范围的end和start元素之间的差异是否相等,然后返回&#34; No&#34;否则转到下一步。
  2. (如果两个范围的差异相等,那么我们需要处理数组元素。)

    1. 初始化HashMap,让它命名为countMap。将数组从range1StartIndex迭代到range1EndIndex并将映射作为每个遇到的字符的条目及其出现的总数。转到下一步。

    2. 将数组从range2StartIndex迭代到range2EndIndex。遇到一个字符,看它是否存在于countMap中。如果它不存在或其计数为0则返回&#34;否&#34;。如果存在,则将计数减1,然后转到下一步。

    3. 迭代countMap的键,如果任何键的计数大于1,则返回&#34;否&#34;,否则转到下一步。

    4. 返回&#34;是&#34;。出口。

答案 1 :(得分:0)

好的,让我们从数组开始:1 2 5 3 5 1 2

这个数组有四个不同的元素(让我们称这个数字为d),我们可以像这样预先计算四个列表:

D[1]: 1 1 1 1 1 2 2
D[2]: 0 1 1 1 1 1 2
D[3]: 0 0 0 1 1 1 1
D[5]: 0 0 1 1 2 2 2

这些包含到该点为止遇到的每个不同元素的数量。此列表的大小显然是d*n

完成后,对于每个查询,您只需通过计算E来检查(x,y)范围内每个不同元素D[E][y]-D[E][x])的数量。两个范围将包含完全相同的元素iff对于所有不同的元素,这个差异是相同的。

显然,如果与n相比,不同元素的数量相对较低,则此解决方案效果最佳,每个查询成本为O(distinct values)

我也省略了一些相当简单的优化,比如如果这两个范围长度相等,或者如果发现任何差异不同,则提前退出。 < / p>

<强>更新

您还可以像这样存储相同的地图:

D'[1]: 0 5
D'[2]: 1 6
D'[3]: 3
D'[5]: 2 4

此地图仅包含原始D[]将更改的位置的索引。此地图的大小始终为n,但计算D[E][y] - D[E][x]现在涉及二进制搜索,仍然会在每个查询成本中保留O(n)最差情况。

但它仍然不适合短距离查询,每个项目的天真比较会产生更好的结果。