如何在scala中查找流中的第一个副本
如何在scala中找到流中的第一个副本 我目前的想法是将每个元素与前面所有元素的如何在scala中查找流中的第一个副本,scala,stream,Scala,Stream,如何在scala中找到流中的第一个副本 我目前的想法是将每个元素与前面所有元素的集合配对。然后,对生成的流调用find 因此,对于每个元素,我们有 在集合中插入:O(1) 测试包含集合中的:O(1) 因此,该算法的总体复杂度似乎为O(n) 有更好的方法吗?您应该使函数尾部递归。按照您拥有它的方式,您几乎是在堆栈上复制整个流的另一个副本。另外,我不明白为什么要复制整个流(以及大量的集合),然后再次扫描以找到dup。在将其添加到集合中时,您可以立即判断它是dup,然后立即停止 也许是这样的:
集合
配对。然后,对生成的流
调用find
因此,对于每个元素,我们有
- 在
集合中插入:O(1)
- 测试
包含
集合中的
:O(1)
有更好的方法吗?您应该使函数尾部递归。按照您拥有它的方式,您几乎是在堆栈上复制整个流的另一个副本。另外,我不明白为什么要复制整个流(以及大量的集合),然后再次扫描以找到dup。在将其添加到集合中时,您可以立即判断它是dup,然后立即停止 也许是这样的:
def firstDup[T](s: Stream[T], seen: Set[T] = Set.empty[T]): Option[T] = s match {
case head #:: tail if seen(head) => Some(head)
case head #:: tail => firstDup(tail, seen + head)
case _ => None
}
上面评论中的布鲁姆过滤器建议对于真正巨大的输入流来说是个好主意。在这种情况下,“外壳”将保持不变,您只需要更改底层的
seen
实现。您希望流有多大?更好的是,元素的多样性如何?这似乎是一种相当理想的方法,尽管对于大型或无限流,它将使用大量内存。您可以尝试使用Bloom filter而不是set进行实验,但是您需要多次检查前面的n个元素,因为它可能返回误报。感谢您提供了更简单的解决方案。只有两个错别字:s/#:/#::和s/empty/empty[T]第一个错别字(现已修复)。另一个不是-那里不需要类型参数,可以推断。如果没有类型参数,我在调用方法[error]时会遇到这个编译错误。注意:没什么,嗯,你是对的。。。我没有想到要把它叫做。。。奇怪的是,firstDup(Seq(1,2,3,4,2).toStream,Set.empty)
实际上可以工作。哦,好吧。。。
def firstDup[T](s: Stream[T], seen: Set[T] = Set.empty[T]): Option[T] = s match {
case head #:: tail if seen(head) => Some(head)
case head #:: tail => firstDup(tail, seen + head)
case _ => None
}