Идея алгоритма в том, что вы не знаете, где находится конец списка.Однако если вы сделаете один указатель в два раза быстрее другого, он достигнет конца так же, как другой достигнет середины.
Инициализация устанавливает середину (first
) и конец (last
)указатели на единственное, что вы знаете изначально: начало списка.Тело цикла перемещает их вперед: first = first.next
перемещается на один шаг вперед, а last = last.next.next
- на два шага вперед.Поскольку last
всегда опережает first
, нет необходимости проверять, может ли first
двигаться вперед.Вместо этого условие цикла проверяет, что обе ссылки, используемые при выполнении шага last
, не являются None
: while last and last.next:
.
Обратите внимание, что если в списке есть один элемент, last
не будетдвигаться, поскольку last.next
равно None
.Однако, с двумя элементами, last
будет двигаться, и так же будет first
.В результате выполняется условие для выбора второй середины из списка с четным числом элементов.