Это очень старая поговорка, что все ответы, которые вы ищете, лежат внутри вас. Чтобы искать его, вы должны спрашивать свое глубокое внутреннее «я» снова и снова, пока не достигнете этой центральной точки, откуда вы разворачиваете все свои ответы и обретаете мудрость. Ответы, которые мы ищем, редко бывают слишком далекими, скорее они слишком близки к нам, чем мы никогда не можем себе представить. В моей жизни, на нескольких этапах, я был удивлен этим фактом. Поскольку я по профессии инженер-программист, я часто пытаюсь объединить жизненную философию с философией кода.

В области программного обеспечения, когда вы ищете ответы (обычно это называется решениями) и когда мы имеем дело с кодом, связанным с ним, именно алгоритмы приводят нас к решениям / ответам. Небольшой фрагмент повторно используемого кода называется функцией, он принимает набор аргументов, работает над конкретными проблемами, для решения которых они предназначены, и сообщает вам результаты. Я часто чувствовал, что наши мыслительные процессы в нашем сознании совпадают с этим. Если взять очень простой пример, если во время посещения магазина я замечаю пару обуви, которая стоит xxx $, первое, что мне приходит в голову, - «Могу ли я себе это позволить? »

Мне кажется, что в этот момент я вызываю в уме логическую функцию isAffordable (xxx $, ‘shoe’). Функциональность учитывает деньги, которые у меня есть в этом месяце, счета, о которых я должен позаботиться, и прогнозы других расходов, которые могут произойти в этом месяце, приоритет обуви среди этих вещей. В результате я могу понять, могу ли я позволить себе эти туфли по этой цене в этом месяце. У всех (каждой системы) есть свой способ или свои собственные реализации этой функции isAffordable (). В большинстве моих мысленных вычислений, проверяющих, доступна ли конкретная вещь, могут использоваться эти функции. Поскольку наш разум представляет собой очень сложную систему, мне часто невозможно реконструировать многие из моих собственных мыслительных процессов.

При использовании функций возникает очень интересная концепция, когда функция вызывает себя снова и снова. Мы называем это рекурсией. Много лет назад, когда я работал инструктором по совместительству для школьников, во время лабораторных экзаменов всякий раз, когда ученики задавали вопрос по проблеме рекурсии, их выражения были очень забавными. Многие из них спрашивали меня, могут ли они предоставить итеративное решение, а не рекурсивный подход. Позже в профессиональной жизни я видел фрагменты кода, в которых для решения проблемы были выбраны итерационные подходы, в которых рекурсивные решения были бы гораздо более элегантными.

Рекурсивные мысли очень распространены в нашей повседневной жизни. Это часто случается в тех случаях, когда нам приходится принимать решения относительно вещей, которые имеют зависимости. Например, когда вы думаете, можете ли вы позволить себе поездку, это обычно связано с множеством зависимостей, начиная с того, можете ли вы позволить себе 10 дней отпуска, пропускать определенные встречи в эти 10 дней, проездные билеты, дорожное снаряжение, состояние здоровья и намного больше. Когда мы обрабатываем каждую отдельную зависимость, чтобы увидеть, насколько она доступна, нам, возможно, придется оценить зависимости этих зависимостей, доступны ли и так далее, пока мы не достигнем точки, когда мы сможем найти вещь без зависимостей, откуда мы можем вернуться. Теперь это спрашивает себя снова и снова, пока мы не найдем решение проблемы, которую пытаемся решить. Чем больше дерево зависимостей для определенных решений, тем сложнее процедура принятия решения.

Теперь, если вы изучали программирование в школе, вы могли бы написать свою первую рекурсивную функцию для печати ряда Фибоначчи или вычисления факториала числа. Эти проблемы очень естественно решать как рекурсивные решения, поскольку их собственные определения содержат рекурсию с ними. Давайте рассмотрим еще одну небольшую проблему, чтобы взглянуть на рекурсию, это также проблема, с которой вы знакомы из уроков программирования в школе.

Чтобы проверить, является ли строка палиндромом или нет.

По определению, палиндром обозначает, является ли строка такой же, даже если она читается в обратном направлении. Классическим примером этого является слово «МАДАМ». Мой любимый пример - «МАЛАЯЛАМ», мой родной язык. Попробуем разные подходы к решению этой проблемы.

Прямой подход был бы

Строка палиндрома - это строка, которая одинакова, даже если она читается справа налево
Если строка перевернута, а перевернутая строка равна исходной строке, ну, это палиндром

Теперь, глядя на это решение, мы можем подумать о других способах решения этой проблемы. Это одна из прелестей области моей работы, существует так много разных способов решения проблемы.

Теперь давайте думать таким образом: если я буду выполнять итерацию от начала до конца строки одновременно, выбирая и сравнивая один символ с обоих концов, и если все сравнения возвращают истину, то я знаю, что левая сторона зеркала строки соответствует правая сторона строки, которая говорит нам, что строка является палиндромом.

Попробуем применить рекурсивный подход к решению этой проблемы?
Давайте вспомним, что все ответы, которые вы ищете, лежат внутри вас.

У нас есть функция isPalindrome (), которая принимает строку и сообщает вам, палиндром это или нет. Затем внутри функции возьмем первую и последнюю буквы строки, проверим, совпадают ли они, и снова спросим функцию, является ли остальная часть строки палиндромом; и давайте делать это снова и снова, пока не достигнем центральной точки.

В центральной точке либо осталось два символа (если общее количество символов в строке четное), либо только один символ. Если есть только один символ, мы точно знаем, что это палиндром, поскольку он читается одинаково слева направо или справа налево. Теперь, если осталось два символа и если они равны, его палиндром (пример: gg).

Ну вот и все!

Мы проверяем, что первый и последний символы данного ввода совпадают, и мы проверяем, является ли остальная часть строки палиндромом, и мы пришли к нашему решению.

Возьмем еще один пример, это один из моих любимых. Эта проблема называется «Высота двоичного дерева». Двоичное дерево - это структура данных, в которой для каждого узла количество дочерних элементов не превышает двух. Это классическая структура данных, которую мы можем использовать во многих процессах принятия решений, которые включают ответы «да» или «нет» для узла, и решения переносят нас на другой узел, включающий другие решения.

Здесь высота дерева представляет собой длину от корневого узла до более дальнего листового узла. В этом примере это будет последний вариант, требующий принятия наибольшего количества решений. Если решения взвешены, высота дерева может обозначать максимальный вес, который может понести любой путь принятия решения. Давайте представим, что на принятие каждого решения уходит некоторое количество времени, тогда в приведенном выше примере наиболее экономичным решением является отказ от закуски, а наиболее трудоемкое решение - связаться с независимым торговым посредником или Uber.

Как рассчитать высоту двоичного дерева? В рекурсивном подходе это довольно просто. Когда мы находимся в узле, мы берем наибольшую из высоты его левого поддерева и правого поддерева, и, поскольку мы уже находимся в узле, мы добавляем 1. Когда дерево достигает своих листовых узлов, когда больше нет решений для принятия, мы знайте, что высота листового узла равна 1. Ну вот и все. Мы перемещаемся от корневого узла к конечному узлу в поисках высоты, задавая один и тот же вопрос каждому узлу, но рекурсивно.

Запоминание результатов

Одна из моих проблем - это «чрезмерное мышление». Я знаю много друзей, у которых такая же проблема. Это ментальное состояние, в котором вы ставите себя в положение, представляете вещи, которые даже почти невозможны, и продолжаете беспокоиться о них. Хотя этот процесс очень вреден для здоровья и представляет собой абсолютную проблему, единственное, что из него выходит, это то, что в одном случае из ста, если вы попадаете в ситуацию (возможно, неожиданную), и если вы уже обдумали ее, вы можете используйте результаты этой мысли. Точно так же в случае рекурсии мы вызываем одну и ту же функцию снова и снова с разными аргументами. Иногда набор аргументов функций мог уже быть оценен в прошлом. Тогда мы можем использовать результаты, если мы их запомнили.

Здесь «память» хранит результаты вычислений, и производительность будет значительно улучшена по сравнению с их запоминанием и без запоминания.

В жизни есть определенные проблемы, они кажутся сложными, решение может показаться очень далеким, но оно будет гораздо ближе, если вы будете искать ответ внутри себя.