fib(n) = fib(n − 1) + fib(n − 2). Нэг дуудлага хоёр шинэ дуудлага үүсгэдэг тул recursion tree хурдан томордог.
Эхлээд жижиг бодлого
fib(4) хэд вэ? fib(4) = fib(3) + fib(2), fib(3) = fib(2) + fib(1), fib(2) = fib(1) + fib(0). fib(1) = 1, fib(0) = 0.
Доороос нь бодвол fib(2) = 1, fib(3) = 2, fib(4) = 3. Гэхдээ function нийт 9 удаа дуудагдана, fib(2) хоёр удаа бодогдоно.
Энгийн аргаас санаа руу
Томьёог шууд кодонд буулгавал хамгийн энгийн recursion гарна: return fib(n - 1) + fib(n - 2);. Бичихэд амар ч нэг дуудлага хоёр шинэ дуудлага үүсгэдэг тул recursion tree хурдан томорно.
fib(n)-ийг бодоход 2·fib(n + 1) − 1 дуудлага хийгддэг. fib(40)-ийг бодоход 300 сая гаруй дуудлага болно. Шалтгаан нь ижил утгыг дахин дахин бодох. Хариуг нэг удаа бодоод хадгалбал (memoization, DP) n удаа л бодно. Энэ animation яг тэр давталтыг харуулахад зориулагдсан.
Нэр томьёо ба тэмдэглэгээ
- fib(n)
- n дэх Фибоначчийн тоо: 0, 1, 1, 2, 3, 5, 8…
- base case
n < 2бол хариу нь n өөрөө.- recursion tree
- Дуудлага бүр нэг цэг, түүний дуудсан дуудлагууд доод талд нь байдаг зураг.
- a, b
a = fib(n - 1),b = fib(n - 2). Хариу ньa + b.
fib(n) = fib(n − 1) + fib(n − 2). Эхний хоёр нь fib(0) = 0, fib(1) = 1. Нэг дуудлага хоёр шинэ дуудлага үүсгэнэ.
- Space тоглуулах
- ←→ алхам
- −+ хурд
- Ажиллаж буй дуудлага
- Хариу хүлээж буй
- Base case
- Хариугаа өгсөн
Фибоначчийн тоо
0, 1, 1, 2, 3, 5, 8 … Дараагийн тоо бүр өмнөх хоёрынхоо нийлбэр: fib(n) = fib(n − 1) + fib(n − 2).
Дараа нь юу болох вэ?
Оноо 0 / 00дараалсан зөв, хамгийн их 0
Animation нэг алхам дээр зогсоно. Дараа нь код юу хийх вэ? Таагаад оноо цуглуул! Нэвтрэх хэрэггүй, оноо чинь энэ төхөөрөмж дээр хадгалагдана.
Юунд хэрэгтэй вэ?
Фибоначчийн дарааллын fib(n)-ийг recursion ашиглан олно. Recursion tree-г харж, ижил дуудлага олон дахин бодогддогийг анзаарна. Ингэснээр DP яагаад хэрэгтэйг мэдэрнэ.
Яаж ажилладаг вэ?
1. Эхний хоёр тоо: fib(0) = 0, fib(1) = 1. n < 2 бол шууд n-ийг буцаана. 2. Үгүй бол fib(n − 1)-ийг бодож a-д хадгална. 3. Дараа нь fib(n − 2)-ыг бодож b-д хадгална. 4. a + b-г буцаана. Анхаар: fib(2), fib(1) гэх мэт ижил дуудлага олон дахин бодогддог. n = 40 үед 300 сая гаруй дуудлага болно. Үүнийг DP хурдасгадаг. Оролт: нэг тоо n.
Яагаад зөв, хэр хурдан бэ?
fib(0), fib(1) хоёр шууд зөв. n-ээс бага бүх утгыг зөв бодно гэвэл fib(n) = fib(n − 1) + fib(n − 2) нь яг томьёо тул зөв. Индукцаар бүх n-д зөв.
Дуудлагын тоо fib(n) шиг өсдөг. n нэгээр нэмэгдэх бүрт ойролцоогоор 1.6 дахин олон болно: хугацаа O(1.6ⁿ). n = 30 бол 2.7 сая, n = 40 бол 330 сая дуудлага. Call stack-ийн гүн нь n тул санах ой O(n).
Түгээмэл алдаа
- Энэ кодыг n = 50 дээр ажиллуулах. Хэдэн минут болж time limit-ээс хэтэрнэ. Memoization эсвэл loop хэрэглэ.
- int ашиглах. fib(47) нь int-ээс хэтэрнэ. Том n бол long long ав.
- Base case-д зөвхөн
n == 1шалгах. fib(0) дуудагдахад зогсохгүй.
Хязгаарын тохиолдол
- n = 0: шууд 0 буцаана, нэг л дуудлага.
- n = 1: шууд 1 буцаана.
- n = 2: 3 дуудлага, хариу 1.
Өөрийгөө шалга
fib(5)-ыг бодоход function хэдэн удаа дуудагдах вэ?
Хариу харах
15 удаа.
2 · fib(6) − 1 = 2 · 8 − 1 = 15.fib(4)-ийг бодоход fib(2) хэдэн удаа бодогдох вэ?
Хариу харах
2 удаа: fib(3) дотор нэг, fib(4)-ийн баруун талд нэг.
fib(10) хэд вэ?
Хариу харах
55.
Гурван дадлага
Hint-ээ нээхээс өмнө өөрөө оролдоорой.
1.fib(5)-ын recursion tree-г зур. Навч болсон fib(1), fib(0) тус бүр хэд вэ?
Hint харах
Навчнуудын нийлбэр хариутай тэнцүү.
Хариу ба тайлбар
fib(1) 5 удаа, fib(0) 3 удаа гарна. Навчны нийлбэр 5 · 1 + 3 · 0 = 5 = fib(5).
2.Хариуг array-д хадгалдаг болгож (memoization) кодыг хурдасга.
Hint харах
memo[n]-ийг −1-ээр дүүргээд, бодсон бол шууд буцаа.Хариу ба тайлбар
if (memo[n] != -1) return memo[n]; return memo[n] = fib(n - 1) + fib(n - 2);. Утга бүрийг нэг удаа бодох тул O(n). fib(90) хүртэл long long-д багтана.3.n шаттай шатаар нэг эсвэл хоёр шатаар алхаж өгсөнө. Хэдэн янзаар өгсөх вэ? n = 4 бол?
Hint харах
Сүүлийн алхам 1 эсвэл 2 шат. Тэгэхээр ways(n) = ways(n − 1) + ways(n − 2).
Хариу ба тайлбар
ways(1) = 1, ways(2) = 2 гэвэл ways(3) = 3, ways(4) = 5. Энэ нь fib(n + 1)-тэй тэнцүү.
Жишээ
Оролт
4
Гаралт
3
Одоо өөрөө бодоод үз
Хичээл
Энэ сэдвийн хичээл удахгүй нэмэгдэнэ.