2016-12-31 5 views
2

スカラのストリームで最初の複製を見つける方法はありますか?スカラのストリームで最初の複製を見つける方法

私の現在のアイデアは、各要素をすべて前の要素のSetとペアにすることです。その後、Streamfindが呼び出されます。

したがって、各要素について、我々はSet

  • 挿入を有する:O(1)Set
  • 試験contains

したがってO(1)、このアルゴリズムの全体的な複雑さはO(n)のように見える。

def firstDuplicate[A](s: Stream[A]) = { 
    def recurse(s: Stream[A], set: Set[A]) : Stream[(A, Set[A])]= 
     (s.head, set) #:: recurse(s.tail, set + s.head) 
    val pairedWithElements = recurse(s, Set.empty) 
    pairedWithElements.find{ case (e, elems) => elems.contains(e)}.get._1 
    } 

もっと良い方法がありますか?

+0

ストリームがどれくらい大きくなると思いますか?どのようにさまざまな要素が出現するのでしょうか? – Chobeat

+1

大規模なストリームや無限ストリームの場合は、大量のメモリを使用することになりますが、かなり最適なアプローチと思われます。 setではなくbloom filterを試してみることもできますが、前のn個の要素を何回も繰り返す必要があるため、誤検出が返される可能性があります。 – adamwy

答えて

3

あなたの関数の末尾を再帰的にする必要があります。あなたが持っている方法では、ストリーム全体のもう一つのコピーをスタック上に作っています。また、私はストリーム全体のコピーを作成しているのか(なぜなら、セットのwhoooole buuunch)、そしてそれをもう一度スキャンして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の実装を変更するだけで済みます。

+0

はるかに簡単なソリューションをありがとう。ちょうど2つのタイプミス:s /#:/#::とs /空/空[T] –

+0

最初の1つはタイプミス(今修正)でした。もう一つはそうではありません。タイプパラームはそこでは不要です。それは推論できます。 – Dima

+0

typeパラメータがないと、メソッドを呼び出すと次のコンパイルエラーが発生します。[エラー]注:Nothing <:Pos、trait SetはタイプAで不変です。 [エラー]次のようなワイルドカード型を調べることができます。 '_ <:Pos'。 (SLS 3.2.10) –

関連する問題