Найдите последний узел кругового связанного списка, размер которого неизвестен, а последний узел указывает на любой другой узел, кроме первого узла связанного списка.

Как найти последний узел кругового связанного списка, размер которого мне неизвестен, и последний узел указывает на любой другой узел, кроме первого узла связанного списка?


person Community    schedule 11.07.2009    source источник
comment
Как это последний узел, если он указывает на другой узел, а не на первый узел?   -  person nik    schedule 12.07.2009


Ответы (6)


Для этого можно использовать алгоритм алгоритм цикла Флойда.

Также см. этот вопрос.

person CAdaker    schedule 11.07.2009
comment
Спасибо за указание на алгоритм Флойда. Очень хорошо. Я видел загадку на этот счет в книге Стива Скиены по алгоритмам и задавался вопросом, какой ответ был бы лучшим. amazon.com/Algorithm-Design-Manual-Steven-Skiena/ дп/1848000693 - person Michael H.; 12.07.2009

По определению, если узел не указывает на первый узел кругового связанного списка,
он не является последним узлом.

Можно здесь поподробнее?

person nik    schedule 11.07.2009
comment
Я думаю, это потому, что мы называем это Circular, не так ли? - person Jonathan; 12.07.2009
comment
Совершенно ясно, что он имеет в виду: связанный список, в котором последний узел указывает на какой-то другой не первый узел в списке, что делает его Q-образным. Не знаю, почему и как вы могли бы получить такой список. - person Sean; 12.07.2009
comment
Вы можете сформировать Qs и крендельки. Круговой список не заканчивается, пока вы не дойдете до головы. И, если вы закончите список, не достигнув головы, список больше не будет круговым. - person nik; 12.07.2009
comment
В этом случае было бы хорошо получить четкое описание списка для соответствующего ответа. - person nik; 12.07.2009
comment
На самом деле, если бы у вас не было списка, в котором узлы могли бы указывать на нескольких преемников, у вас не было бы кренделя. В любом случае, хотя он и не является строго круговым, если у вас есть четко определенная голова, то ваш четко определенный конец — это последний новый узел, к которому вы попадаете при обходе списка, начиная с головы. Я думаю, что называть круговой список в форме Q, а затем уточнять его, говоря, что у него есть хвост или фраза в ОП, является допустимым. Я согласен, что больше подробностей было бы хорошо, хотя. Я также чувствую, что это домашнее задание или вопрос для интервью. - person Sean; 12.07.2009
comment
Циклический связанный список не обязательно должен иметь последний узел, соединенный с первым узлом. Последний узел может указывать на любой узел в списке, включая себя и голову. - person Oleksiy; 09.12.2013

Странный список... зачем вам что-то подобное? Но все таки...

Вы можете просто перебрать все узлы и остановиться, как только следующий узел окажется тем, который вы уже посетили. Текущий узел будет вашим ответом.

Вам нужен какой-то способ отслеживать, какие узлы были посещены. Добавьте логический флаг к каждому узлу или используйте какой-либо набор данных с быстрой вставкой и поиском (например, набор хэшей).

person Thomas    schedule 11.07.2009

Может быть, добавить параметр к узлам списка, который сообщает вам, если вы в конце? Я думаю, это не будет проблемой.

В противном случае вы можете вспомнить узлы, которые вы уже посещали. Когда следующий узел уже посещен, вы находитесь в конце.

person izidor    schedule 11.07.2009

Алгоритм цикла Флойда не даст последний элемент списка. Он только скажет, есть ли цикл или нет.

Определение последнего будет заключаться в том, что при обходе списка в последовательном сканировании, начиная с первого, все элементы до него и последнего не видны раньше (значение указателя). Последним будет первый элемент, который уже был замечен в этом последовательном сканировании.

Простое решение — пометить посещенные элементы, чтобы можно было легко обнаружить уже просмотренный элемент. Флаг может быть интрузивным, т. е. путем изменения бита в элементе, или внешним, с использованием хэш-таблицы для хранения значений указателя.

Поскольку нам нужно иметь возможность проверить, был ли уже посещен элемент, я не вижу другого решения.

person chmike    schedule 14.07.2009

Я могу уточнить, как использовать алгоритм Флойда для решения этой проблемы, но я не понимаю объяснения одного шага.

  1. Пусть 2 указателя проходят по связанному списку, указатель 1 проходит со скоростью 1 узел за итерацию, а второй — со скоростью 2 узла.
  2. Когда указатели встречаются, мы находимся в цикле, и мы находимся на некотором расстоянии до того, как указатель 1 достигнет конца цикла (мы знаем, что указатель 1 не достиг конца цикла, потому что если цикл равен расстоянию d, а указатель 2 движется на удвоенной скорости). скорость 1, указатель 1 дважды зациклит цикл, прежде чем указатель 1 сделает это один раз)
  3. Таким образом, поскольку они встретились до того, как указатель 1 полностью прошел цикл, мы знаем, что точка встречи — это d узлов от начала и k узлов внутри цикла (pos = d + k).
  4. Если мы установим указатель 1 в положение 0 и снова запустим обе точки (но с той же скоростью, равной 1 узлу за итерацию), они встретятся в начале цикла.
  5. Поскольку мы знаем начало цикла, найти конец тривиально.

Я не совсем понимаю, почему шаг 4 верен, но мой друг объяснил мне решение.

person i8abug    schedule 11.10.2011