Нет причин, по которым вам нужно использовать номер два. Подойдет любой размер шага (конечно, кроме одного).
Чтобы увидеть, почему это работает, давайте посмотрим, почему алгоритм Флойда работает в первую очередь. Идея состоит в том, чтобы подумать о последовательности x 0 , x 1 , x 2 , ..., x n , .. из элементов связанного списка, который вы посетите, если начнете с начала списка, а затем продолжите идти по нему, пока не дойдете до конца. Если список не содержит цикл, то все эти значения различны. Если же он содержит цикл, то эта последовательность будет повторяться бесконечно.
Вот теорема, которая заставляет алгоритм Флойда работать:
Связанный список содержит цикл тогда и только тогда, когда существует положительное целое число j, такое что для любого положительного целого числа k, x j = x jk .
Давай докажем это; это не так сложно. Для случая «если», если такой j существует, выберите k = 2. Тогда мы получим это для некоторых положительных j, x j = x 2j и j & ne; 2j, и поэтому список содержит цикл.
Для другого направления предположим, что список содержит цикл длиной l, начинающийся с позиции s. Пусть j будет наименьшим кратным l больше s. Тогда для любого k, если мы рассмотрим x j и x jk , так как j кратно длине цикла, мы можем думать о x jk как Элемент формируется, начиная с позиции j в списке, затем делая j шагов k-1 раз. Но каждый раз, когда вы делаете j шагов, вы в конечном итоге возвращаетесь к тому, с чего начинали в списке, потому что j кратно длине цикла. Следовательно, x j = x jk .
Это доказательство гарантирует вам, что если вы выполните какое-либо постоянное число шагов на каждой итерации, вы действительно нажмете на медленный указатель. Точнее, если вы делаете k шагов на каждой итерации, то в конечном итоге вы найдете точки x j и x kj и обнаружите цикл. Интуитивно понятно, что люди, как правило, выбирают k = 2, чтобы минимизировать время выполнения, поскольку на каждой итерации вы выполняете наименьшее количество шагов.
Мы можем проанализировать время выполнения более формально следующим образом. Если список не содержит цикла, быстрый указатель достигнет конца списка после n шагов в течение O (n) времени, где n - количество элементов в списке. В противном случае два указателя встретятся после того, как медленный указатель предпримет j шагов. Помните, что j является наименьшим кратным l больше s. Если s & le; l, тогда j = l; в противном случае, если s> l, то j будет не более 2 с, и поэтому значение j равно O (s + l). Поскольку l и s не могут превышать количество элементов в списке, это означает, что j = O (n). Однако после того, как медленный указатель сделал j шагов, быстрый указатель сделает k шагов для каждого из j шагов медленного указателя, поэтому он предпримет O (kj) шагов. Поскольку j = O (n), чистая среда выполнения не более O (nk). Обратите внимание, что это говорит о том, что чем больше шагов мы сделаем с помощью быстрого указателя, тем дольше алгоритм завершает работу (хотя и пропорционально). Выбор k = 2, таким образом, минимизирует общее время выполнения алгоритма.
Надеюсь, это поможет!