Изучение эффективных алгоритмов

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

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

Есть ли определенный способ думать о проблемах, которые помогут вам придумать как можно более эффективное решение, или это просто вопрос практики и/или запоминания?

Кроме того, какие онлайн-ресурсы вы можете порекомендовать, чтобы научить вас различным эффективным алгоритмам для разных проблем?

Ответы

Ответ 1

Данные доминируют. Если вы разрабатываете свою программу вокруг правильных абстрактных структур данных (ADT), вы часто получаете чистый дизайн, алгоритмы следуют вполне естественно, а когда производительность отсутствует, вы должны иметь возможность "подключать" более эффективные.

Сильный фон в математике и логике помогает здесь, так как он позволяет вам визуализировать вашу программу на высоком уровне как взаимодействие между функциями, наборами, графиками, последовательностями и т.д. Затем вы решаете, нужно ли заказывать множество (например, сбалансированные операции BST, O (lg n)) или нет (хеш-таблицы, операции O (1)), какие операции необходимо поддерживать на последовательностях (похожие на векторные или списки) и т.д.

Если вы хотите изучить некоторые алгоритмы, получите хорошую книгу, такую ​​как Cormen et al. и попытайтесь реализовать основные структуры данных:

  • деревья двоичного поиска
  • общие двоичные деревья поиска (которые работают не только int, либо строки)
  • хеш-таблицы
  • очереди приоритетов/кучи
  • динамические массивы

Ответ 2

Введение в алгоритмы - отличная книга, которая заставит вас задуматься об эффективности разных алгоритмов/структур данных.

Авторы книги также учат курс алгоритмов MIT. Вы можете найти большинство лекций здесь

Ответ 3

Я бы сказал, что при разработке хороших алгоритмов (которые на самом деле являются частью хорошего дизайна IMHO), вы должны разработать способ мышления. Это лучше всего сделать, изучая дизайн алгоритма. К изучению я не имею в виду просто знание всех общих алгоритмов, рассмотренных в учебнике, но на самом деле понимание того, как и почему они работают, и возможность применить основную идею, содержащуюся в них, к актуальным проблемам, которые вы пытаетесь решить.

Я бы предложил прочитать хорошую книгу об алгоритмах (мой любимый CLRS). Для онлайн-ресурса я бы рекомендовал серию статей в Учебниках по алгоритму TopCoder.

Я не понимаю, почему вы упомянули практику и запоминание на одном дыхании. Запоминание вам не поможет (возможно, вы уже знаете это), но практика важна. Если вы не можете применить то, чему научились, его не изучают. Вы можете практиковать на различных сайтах онлайн-программирования/головоломки, таких как SPOJ, Project Euler и PythonChallenge.

Ответ 4

Рекомендации: Прежде всего, я рекомендую книгу "Введение в алгоритмы, второе издание от corman", у большой книги есть большинство (если не все) алгоритмов, которые вам понадобятся. (Некоторые из наиболее важных тем - алгоритмы сортировки, кратчайшие пути, динамическая программирование, множество структур данных, таких как bst, хэш-карты, кучи).

Еще один отличный способ изучить алгоритмы - http://ace.delos.com/usacogate, отличная практика после начала.

На ваши вопросы вы просто привыкнете писать хороший быстрый код, после небольшой практики вы просто не захотите писать неэффективный код.

Ответ 5

Хотя я думаю, что @larsmans правилен, поскольку понимание логики и математики - это быстрый способ понять, как выбрать полезные ADT для решения данной проблемы, изучение существующих решений может быть более поучительным для тех из нас, кто борется с этими темами. В частности, обзор кода установленного программного обеспечения (OSS), который решает какую-то аналогичную проблему, как тот, который вас интересует.

Я нахожу особенно хороший метод для этого метода исследования, рассматривая модульные тесты такого проекта. Apache Lucene, например, имеет репозиторий управления версиями, содержащий многочисленные примеры. Хотя он не раскрывает основные алгоритмы, он помогает отслеживать определенную функциональность, которая решает определенную проблему. Это дает возможность изучить его внутренности, т.е. Интересный алгоритм. В случае Lucene инвертированные индексы приходят на ум.

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