我有一大堆间隔(开始,结束)是连续的和不重叠的。给定一个数字,我想知道它属于哪个区间。
我目前正在编写基于二进制搜索的解决方案 - 我想知道使用标准库数据结构(如TreeMap或TreeSet)是否可行。
答案 0 :(得分:0)
如果我理解你的需要,你有一个范围列表,如(1,5),(6,10),(11,18)等等。当给出类似4的输入时,您希望返回包含此输入的范围。
这是Scala中的一个版本:
scala> val input = List((1,5), (6,10),(11,18))
input: List[(Int, Int)] = List((1,5), (6,10), (11,18))
scala> input.filter(elem => 4 <= elem._2 && 4 >= elem._1)
res1: List[(Int, Int)] = List((1,5))
您可以通过将其解压缩到方法并传递输入参数来扩展它。
您可以根据用例替换所需的集合类型。看看这里的集合性能特征:
http://docs.scala-lang.org/overviews/collections/performance-characteristics.html
如果要使用TreeSet,可以执行以下操作:
scala> val in = TreeSet((1,5),(6,10),(11,15))
in: scala.collection.immutable.TreeSet[(Int, Int)] = TreeSet((1,5), (6,10))
scala> in.filter(elem => 4 <= elem._2 && 4 >= elem._1)
res2: scala.collection.immutable.TreeSet[(Int, Int)] = TreeSet((1,5))
答案 1 :(得分:0)
是的,可以使用标准Java或Scala的TreeMap
(下面是RB树)。
代码:
import scala.collection.immutable.TreeMap
val ranges = TreeMap((1, 5), (8, 10), (11, 18))
def contains(intervals: TreeMap[Int, Int])(el: Int) =
intervals.to(el).lastOption.exists(_._2 >= el)
(-1 to 20).foreach { i =>
println(s"$i ${contains(ranges)(i)}")
}
打印:
-1 false
0 false
1 true
2 true
3 true
4 true
5 true
6 false
7 false
8 true
9 true
10 true
11 true
12 true
13 true
14 true
15 true
16 true
17 true
18 true
19 false
20 false
这个想法是使用to
方法,该方法返回一个小于或等于给定元素的键的映射投影。如果地图包含与给定点相交的间隔,则此间隔将是投影中的最大键。因此,唯一剩下的就是检查该区间的值(右边界)是否大于相关元素。
to
和lastOption
方法都适用于O(log n)
的RB树。
此实现假设范围包含范围,但应该很容易修改此代码以获得独占范围。