Причина на самом деле очень проста: когда функция возвращает True
, нет смысла кэшировать результат, потому что этот кэшированный результат никогда не будет прочитан, потому что после этого больше не будет вызовов функции, потому что когда рекурсивный вызов возвращает True
(что означает «я нашел путь к ( dstR , dstC )»), весь стек вызовов быстро раскручивается при каждом вызове немедленно возвращает True
(все еще означает "Я нашел путь к ( dstR , dstC )").
Итак, это направление мысли:
[& hellip;] Я думал, что Решение 1 будет лучше, чем Решение 2, поскольку оно кэширует каждый результат, а не только ошибочные пути [& hellip;]
не работает, потому что эти дополнительные кеши - это просто бесполезные записи, которые никогда не будут прочитаны (кроме сразу , поскольку, как указывает Роб Майофф, вы используете return cache[currentRow][currentColumn]
в решении № 1, но конечно, это можно легко изменить, просто вернув локальную переменную).
Это частично из-за короткого замыкания or
; в выражении вроде
findPathCached( cache, grid, dstR, dstC, currentRow, currentColumn+1 ) or \
findPathCached( cache, grid, dstR, dstC, currentRow+1, currentColumn )
второй вызов функции не произойдет, если первый вернет True
.
Если вы хотите, чтобы дополнительное кэширование в решении № 1 было полезным, вы можете подумать о проблеме, когда это короткое замыкание невозможно; например, вместо того, чтобы просто возвращать True
или False
, чтобы указать, возможен ли путь, попробуйте вернуть , сколько путей возможно & mdash; Итак, 0
вместо False
, положительное число вместо True
и +
вместо or
. Вы внезапно обнаружите, что Решение № 1 намного быстрее, потому что оно может охватывать всю сетку во времени пропорционально размеру сетки, тогда как Решение № 2 будет повторять огромное количество вызовов и займет гораздо больше времени.
Кстати, вы можете решить эту проблему, используя только O (мин ( m , n )) дополнительное пространство вместо O ( mn ) дополнительное пространство, с немного другим подходом, который все еще требует только O ( mn ) времени. В частности: вы можете выполнять итерацию по строкам сетки, и для каждой из них создать список, из которых ячейки в строке доступны из (0, 0). Список для данной строки зависит только от списка из предыдущей строки, поэтому вам не нужно сохранять все старые списки во время итерации. (Это на самом деле O ( n ) дополнительное пространство, но я говорю, что вы можете сделать это в O (мин ( м , * 1068) * n )) дополнительное пространство, потому что вы можете начать с проверки, какое измерение больше, и перебирать столбцы вместо строк, если выясняется, что строки длиннее столбцов.)