seq
почти всегда O(n)
. A seq
aka IEnumerable<T>
по существу:
type Enumerator<'a> = {
getNext : unit -> 'a option
}
type Seq<'a> = {
getEnumerator: unit -> Enumerator<'a>
}
Каждый раз, когда вы оцениваете последовательность, создается новый Enumerator
, который фиксирует состояние перечисления. Затем постоянно вызывается getNext
, пока последовательность не завершится.
Вы можете убедиться в этом сами, если в любой момент заменить seq
на
source |> Seq.map(fun x -> printfn "Eval %A" x; x)
Давайте покажем вызовы на getEnumerator
, а также:
let sq =
seq {
let mutable ctr = 0
do printfn "Init _"
while true do
ctr <- ctr + 1
printfn "Yield %d" ctr
yield ctr
}
seqIdWithUnfold (sq |> Seq.take 3) |> Seq.toList |> printfn "%A"
И есть вывод:
Init _
Yield 1
Init _
Yield 1
Yield 2
Init _
Yield 1
Yield 2
Yield 3
Init _
Yield 1
Yield 2
Yield 3
[1; 2; 3]
Здесь показан шаблон classi c n(n+1)/2
.
You можно увидеть, что сложность будет содержать n + n 2 членов.
Если вы можете использовать список, вы получите O(n)
вместо O(n^2)
.
Если вы действительно хотите O(1)
, используйте массивы.