Есть одна главная вещь, которая значительно улучшит производительность, взяв ее от экспоненциального к линейному времени.
Не пересчитывайте рекурсию, сохраняйте ее как промежуточный результат.
Во внутреннем cond
выражении (maximum (rest x))
вычисляется дважды. Однажды в вопросе о первой ветви, и однажды ответ второй ветви.
(cond
[(>= (first x) (maximum (rest x))) (first x)]
[else (maximum (rest x))])
В общем случае, когда первый вопрос неверен, (maximum (rest x))
будет пересчитан, удвоив работа, которую он должен сделать. Что еще хуже, это удвоение может произойти на каждом уровне рекурсии в худшем случае, когда максимальное значение находится в конце. Это то, что делает его экспоненциальным.
Чтобы исправить это, вы можете использовать local
, чтобы определить и назвать промежуточный результат.
(local [(define maxrst (maximum (rest x)))]
(cond
[(>= (first x) maxrst) (first x)]
[else maxrst]))
Это требует большого -О сложность от экспоненциальной до линейной по длине ввода.
Существуют и другие потенциальные оптимизации, такие как использование хвостовых вызовов, но они не так важны, как сохранение промежуточного результата, чтобы избежать повторного ввода. вычисление рекурсии.
Этот метод повышения производительности с использованием определений local
также описан в Как разрабатывать программы 2e Рис. 100: Использование локальных для повышения производительности .