{"componentChunkName":"component---src-templates-post-js","path":"/javascript/recursivno-opredelyaem-chisla-fibonacci-s-pomoshiu-memoizacii-v-javascript/","result":{"pageContext":{"slug":"recursivno-opredelyaem-chisla-fibonacci-s-pomoshiu-memoizacii-v-javascript","content":"\n<p>В этой статье рассказывается о том, как определить и оперировать числами Фибоначчи с помощью рекурсии и мемоизации на JavaScript.</p>\n\n\n\n<p>Я постепенно расскажу про каждый момент в этой задаче, с объяснениями и примерами кода.</p>\n\n\n\n<p><em>P.S Очень надеюсь, что эта статья поможет явисту Ростиславу узнать, что такое мемоизация и рекурсивный ряд чисел Фибоначчи.</em></p>\n\n\n\n<h2>Фибоначчи и рекурсия</h2>\n\n\n\n<p>Вообще, рекурсивный подход в решении этой задачи считается плохой практикой из-за высокого runtime complexity. Это решение будет O(log n). А если представить большие числа, то сложно представить насколько тяжелой будет операция.</p>\n\n\n\n<p>Давайте посмотрим на рекурсивное решение этой задачки:</p>\n\n\n\n<pre class=\"wp-block-code javascript\"><code>const fibo = (n) => {  \n  if (n &lt; 2) {\n    return n;\n  }\n  return fibo(n - 1) + fibo(n - 2);\n};</code></pre>\n\n\n\n<p>Суть в том, что мы последовательно запускаем функцию внутри себя же, делая ряд вычислений. Но давайте разберемся, что же там происходит на самом деле. Вот визуальное представление:</p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" width=\"700\" height=\"305\" src=\"https://stasonmars.ru/wp/wp-content/uploads/2021/02/fibkjnfklj.jpeg\" alt=\"\" class=\"wp-image-220\" srcset=\"https://stasonmars.ru/wp/wp-content/uploads/2021/02/fibkjnfklj.jpeg 700w, https://stasonmars.ru/wp/wp-content/uploads/2021/02/fibkjnfklj-300x131.jpeg 300w\" sizes=\"(max-width: 700px) 100vw, 700px\" /></figure>\n\n\n\n<p>Давайте взглянем на три блока слева. А именно <code>f(2)</code> и затем на <code>f(1)</code> и <code>f(0)</code>. Тут мы находим второй элемент в ряде чисел, начинающимся с <code>0</code>.</p>\n\n\n\n<p>Напоминаю, ряд чисел Фибоначчи это:</p>\n\n\n\n<blockquote class=\"wp-block-quote\"><p>0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144 и так далее.</p></blockquote>\n\n\n\n<p>Тут мы отдаем <code>fibo</code> значение <code>2</code>, так как мы хотим высчитать <code>fibo(2)</code>. Как вы видите сверху мы видим специальное условие когда число равно 2-м и не меньше двух.</p>\n\n\n\n<p>Дальше отработают следующие строчки кода:</p>\n\n\n\n<p><code>fibo(n - 1) + fibo(n - 2)</code></p>\n\n\n\n<p>Замените <code>n</code> на <code>2</code> и мы получим <code>fibo(1) + fibo(0)</code></p>\n\n\n\n<p>Следующим шагом будет нахождение значений двух условий, а именно <code>fibo(0)</code> и <code>fibo(1)</code>. Тут для каждого случая нам придётся заново запускать метод <code>fibo</code> и именно в этом моменте и начинается рекурсия.</p>\n\n\n\n<p>В общем, мы получаем буквально следующее:</p>\n\n\n\n<p><code>fibo(2) = fibo(1) + fibo(0) = 1 + 0 = 1</code></p>\n\n\n\n<p>Давайте ещё немного разберем рекурсию, но уже с <code>fibo(3)</code>.</p>\n\n\n\n<p><code>fibo(3) = fibo(2) + fibo(1)</code></p>\n\n\n\n<p>Используя рекурсию мы получаем мы получаем следующее продолжение:</p>\n\n\n\n<p><code>fibo(2) + fibo(1), где fibo(2)</code> рекурсивно станет <code>(fibo(1) + fibo(0)) + fibo(1)</code>, где в результате мы получим <code>1 + 0 + 1 = 2</code>.</p>\n\n\n\n<p>Сейчас структура древа, описанного выше должна стать для вас более понятной. Рекурсия будет происходить вплоть до конца каждой ветви пока значение не будет <code>1</code> или <code>0</code>.</p>\n\n\n\n<p>А теперь самое интересное. Посмотрите на количество одинаковых аргументов в этом древе. Их несколько: <code>4, 3, 2</code> и все они будут отрабатывать снова и снова при вызове рекурсии.</p>\n\n\n\n<p>И тут нам на помощь приходит <strong>мемоизация</strong>.</p>\n\n\n\n<h2 class=\"javascript\">Мемоизация</h2>\n\n\n\n<p>Мемоизация это имплементация сложных рекурсивных или же итеративных функций более быстрым способом. Как? Кэшируя значения отдаваемые функцией при её первоначальном запуске.</p>\n\n\n\n<p>Когда мы отдаём функции мемоизации уже использованное значение, то оно отдаст готовое значение, сохраненное в кэше и не будет запускать функцию снова. К чему это приведет? К тому ускорению производительности, очевидно же. Вашему коду не надо будет пересчитывать то, что уже давно посчитано.</p>\n\n\n\n<p>Круто звучит, да? Тогда давайте посмотрим на пример мемоизации, что понять его более детально:</p>\n\n\n\n<pre class=\"wp-block-code javascript\"><code>function memo(func){\n  const cache = {};\n    return function(){\n      const key = JSON.stringify(arguments);\n      if (cache&#91;key]){\n        return cache&#91;key];\n      }\n      else{\n        val = func.apply(null, arguments);\n        cache&#91;key] = val;\n        return val; \n      }\n  }\n};</code></pre>\n\n\n\n<p>Мы отдаём так называемое анонимное замыкание, которое может наследовать любую переменную или в нашем случае функцию, переданную memo. Затем мы можем смело играться с объектом аргументов этой функции.</p>\n\n\n\n<pre class=\"wp-block-code javascript\"><code>const memoFib = memo((n) => {\n    if (n &lt; 2) {\n        return n;\n    }\n    return memoFib(n - 1) + memoFib(n - 2);\n});</code></pre>\n\n\n\n<p>Например, запустив её с <code>memoFib(8)</code> мы получим <code>21</code>, а объект с мемоизированными значениями будет выглядеть так:</p>\n\n\n\n<pre class=\"wp-block-code javascript\"><code>{\n\t  {\"0\":0}: 0,\n\t  {\"0\":1}: 1,\n\t  {\"0\":2}: 1,\n\t  {\"0\":3}: 2,\n\t  {\"0\":4}: 3,\n\t  {\"0\":5}: 5,\n\t  {\"0\":6}: 8,\n\t  {\"0\":7}: 13\n}</code></pre>\n\n\n\n<p></p>\n","type":"js","date":"2021-02-11T16:25:38.000Z","acf":{"seo_desc":"В этой статье рассказывается о том, как определить и оперировать числами Фибоначчи с помощью рекурсии и мемоизации на JavaScript.","keywords":"Фибоначчи javascript, рекурсия фибоначчи javascript, фибоначчи рекурсией мемоизация","pub_date":"2021-02-11","tags":"JavaScript, алгоритмы, JavaScript советы"},"title":"Рекурсивно определяем числа Фибоначчи с помощью мемоизации в JavaScript","id":"6c644d43-c324-5c7e-b647-22e3724bb74f","excerpt":"<p>В этой статье рассказывается о том, как определить и оперировать числами Фибоначчи с помощью рекурсии и мемоизации на JavaScript.</p>\n","featured_media":{"source_url":"https://stasonmars.ru/wp/wp-content/uploads/2021/02/recursivefibonaccikfjn.jpg"},"interesting":[{"title":"JavaScript. Почему 3 + true = 4? И другие хитрые уравнения приведения типов","slug":"javascript-pochemu-3true4-i-drugie-hitrye-uravneniya-privedeniya-tipov","type":"js"},{"title":"Лучшие советы и уловки JavaScript","slug":"luchshie-sovety-i-ulovki-javascript","type":"js"},{"title":"Рекурсивно определяем числа Фибоначчи с помощью мемоизации в JavaScript","slug":"recursivno-opredelyaem-chisla-fibonacci-s-pomoshiu-memoizacii-v-javascript","type":"js"}]}},"staticQueryHashes":["3576131997","63159454"]}