10.2 Výpočet Fibonacciho čísla
Algoritmus 10.1 (FibRec)
Pozorování
Časová složitost volání funkce FibRec(n)
je \(\Theta(F(n))\), kde \(F(n)\) je \(n\)-té Fibonacciho číslo,
tedy \(\Theta(\Phi^{n+1})\), kde \(\Phi \approx 1,61\) je hodnota zlatého řezu.
Důkaz časové složitosti FibRec
- Ve stromu rekurzivních volání (SRV) je každý vrchol buďto list nebo vnitřní vrchol s přesně 2 syny (SRV je plný binární strom).
- Počet vnitřních vrcholů je tedy nejvýše počet listů.
- Libovolný vnitřní vrchol vrací součet hodnot ze svých synů, neboli součet hodnot všech listů ležících pod ním.
- Každý list přitom vrací hodnotu 1.
- Celkem tedy SRV obsahuje přesně \(F(n)\) listů.
Výpočet Fibonacciho čísla - memoizace
- Použijeme tabulku \(T\), na počátku obsahující nedefinované hodnoty.
- Hodnotu \(F(i)\) zapíšeme do \(T[i]\), jakmile na ni při provádění rekurzivního algoritmu poprvé narazíme a poprvé ji vypočteme.
- Při každém rekurzivním volání se nejdřív podíváme do políčka \(T\), odpovídajícího danému podproblému, zda již neobsahuje dříve vypočtené řešení.
- Pokud ano, rekurzi nevoláme a vezmeme hodnotu z tabulky.
- Pokud ne, voláme rekurzi.
- Této technice se říká memoizace.
Algoritmus 10.2 (FibMem)
Pozorování
Časová složitost volání funkce FibMem(n)
je \(O(n)\).
Důkaz časové složitosti FibMem
- K rekurzivnímu volání nyní dojde jedině tehdy, vyplňujeme-li dosud nedefinované políčko tabulky.
- Protože na počátku jsou všechna políčka prázdná, stane se toto \(n\)-krát, z toho dvakrát triviálně pro \(F(1)\) a \(F(2)\).
- SRV má tedy \(n − 2\) vnitřních vrcholů a tedy \(n − 1\) listů.
- Celkem tedy \(O(n)\) vrcholů, kde v každém strávíme \(O(1)\) čas
Výpočet Fibonacciho čísla - iterace
- Všimněme si ale, že pokud tabulku \(T\) budeme vyplňovat od nejmenších hodnot k největším, vůbec rekurzi nepotřebujeme a stačí jednoduchá iterace. (topologické uspořádání)
Algoritmus 10.3 (FibIter)
Pozorování
FibIter(n)
funguje korektně a má časovou složitost \(O(n)\).