Scala 查找范围内的缺失值

Scala find missing values in a range

对于给定的范围,例如

val range = (1 to 5).toArray
val ready = Array(2,4)

缺失值(未就绪)是

val missing = range.toSet diff ready.toSet
Set(5, 1, 3)

实际用例包括数以千计的范围实例,其中(可能)有数以千计的缺失就绪值。 Scala 有没有更省时的方法?

diff 操作在 Scala 中实现为左 ope运行d 上的 foldLeft,其中右 ope运行d 的每个元素都从左集合。假设左右 ope运行d 分别有 mn 元素。

ArrayRange 对象上调用 toSet 将 return 一个 HashTrieSet,这是一个 HashSet 实现,因此,提供复杂度几乎 O(1) 的删除操作。因此,diff 操作的总体复杂度为 O(m).

现在考虑一种不同的方法,我们会发现这实际上非常好。还可以通过对两个 运行ges 进行排序然后以合并排序方式遍历它们一次以消除出现在两个 运行ges 中的所有元素来解决该问题。这会给你带来 O(max(m, n) * log(max(m, n))) 的复杂度,因为你必须对两个 运行ges.

进行排序

更新

我 运行 一些实验来研究是否可以通过使用可变哈希集而不是不可变哈希集来加快计算速度。如下表所示的结果取决于 rangeready 的大小比例。

如果 ready.size/range.size < 0.2,使用不可变哈希集似乎更有效。高于此比率,可变哈希集优于不可变哈希集。

对于我的实验,我设置 range = (1 to n),其中 nrange 中的元素数。对于 ready,我选择了 range 的 运行dom 子集,其中包含相应的元素数。我每个 运行 重复了 20 次并总结了用 System.currentTimeMillis().

计算的时间
range.size == 100000
+-----------+-----------+---------+
| Fraction  | Immutable | Mutable |
+-----------+-----------+---------+
| 0.01      |        28 |     111 |
| 0.02      |        23 |     124 |
| 0.05      |        39 |     115 |
| 0.1       |       113 |     129 |
| 0.2       |       174 |     140 |
| 0.5       |       472 |     200 |
| 0.75      |       722 |     203 |
| 0.9       |       786 |     202 |
| 1.0       |       743 |     212 |
+-----------+-----------+---------+

range.size == 500000
+-----------+-----------+---------+
| Fraction  | Immutable | Mutable |
+-----------+-----------+---------+
| 0.01      |        73 |     717 |
| 0.02      |       140 |     771 |
| 0.05      |       328 |     722 |
| 0.1       |       538 |     706 |
| 0.2       |      1053 |     836 |
| 0.5       |      2543 |    1149 |
| 0.75      |      3539 |    1260 |
| 0.9       |      4171 |    1305 |
| 1.0       |      4403 |    1522 |
+-----------+-----------+---------+