Это добавляет пару оптимизаций к хорошему решению @ GreggLind, сокращая время выполнения вдвое:
def is_palindrome(n):
s = str(n)
return s == s[::-1]
def biggest():
big_x, big_y, max_seen = 0,0, 0
for x in xrange(999,99,-1):
# Optim. 1: Nothing in any row from here on can be bigger.
if x*x < max_seen: break
for y in xrange(x, 99,-1): # so we don't double count
# Optim. 2: break, not continue
if x*y < max_seen: break # since we're decreasing,
# nothing else in the row can be bigger
if is_palindrome(x*y):
big_x, big_y, max_seen = x,y, x*y
return big_x,big_y,max_seen
biggest()
# (993, 913, 906609)
Линия
if x*x < max_seen: break
означает, что как только мы дойдем до точки, где x меньше, чем sqrt самого большого палиндрома, который мы видели, нам не только не нужно больше исследовать какие-либо факторы в этой строке; нам даже не нужно вообще исследовать какие-либо строки, поскольку все оставшиеся строки будут начинаться с числа, меньшего, чем текущее значение x.
Это не уменьшает количество вызовов is_palindrome()
, но означает намного меньше итераций внешнего цикла. Значение x
, на которое он разбивается, составляет 952, поэтому мы исключили проверку 853 строк (хотя и «меньших», благодаря другим break
).
Я также заметил, что
if x*y < max_seen: continue
должно быть
if x*y < max_seen: break
Мы пытаемся замкнуть всю строку, а не только текущую итерацию внутреннего цикла.
Когда я запускал этот скрипт с помощью cProfile, совокупное время для biggest()
до оптимизации составляло в среднем около 56 мсек. Оптимизация сократила его примерно до 23 мсек. Любая оптимизация сама по себе принесет большую часть этого улучшения, но первая из них немного более полезна, чем вторая.
person
LarsH
schedule
03.01.2013