Программа курса:
Разбор задачи: Цикл в связном списке
Предложенный нами код решения:
def has_cycle(head, pos):
"""
Проверяет, существует ли цикл в связанном списке.
:param head: Список чисел, представляющий элементы связанного списка.
:param pos: Индекс, указывающий на элемент, к которому подключен хвост (если pos == -1, цикла нет).
:return: True, если в списке есть цикл, иначе False.
"""
# Если список пустой или состоит из одного элемента
if not head or len(head) == 1:
return False
# Создаем словарь, чтобы отслеживать уже посещенные индексы
visited = set()
# Проходим по всем элементам списка
current = 0
while current != -1: # Пока не дошли до конца списка (где current == -1)
if current in visited:
return True # Если уже встречали этот индекс, значит есть цикл
visited.add(current) # Добавляем индекс в множество посещенных
# Переходим к следующему элементу
current = head[current] if current < len(head) else -1
if current == -1 and pos != -1:
# Если мы достигли конца списка и pos не -1, то создаем цикл
current = pos
return FalseЗадача заключается в том, чтобы определить, есть ли цикл в связанном списке. Связанный список представлен в виде массива чисел head, где каждое число указывает на следующий элемент, а значение -1 обозначает конец списка. Параметр pos указывает на индекс элемента, к которому подключен хвост списка, если цикл существует.
Алгоритм решения:
- Проверка на пустоту и одноэлементный список: Если список пустой (
not head) или состоит из одного элемента (len(head) == 1), то очевидно, что в списке не может быть цикла. В таких случаях функция сразу возвращаетFalse. - Использование множества для отслеживания посещенных элементов: Для эффективной проверки наличия цикла используется множество (
visited). Множество позволяет хранить уникальные элементы и быстро проверять, встречались ли они уже в процессе обхода списка. Если мы обнаружим, что текущий элемент уже находится в множестве, значит, мы обнаружили цикл. - Обход списка: Начинаем с первого элемента списка (индекса 0). Пока не дойдем до конца списка (индекс
-1), продолжаем двигаться по элементам.- Если текущий элемент уже встречался (он присутствует в множестве
visited), значит, это цикличный список, и возвращаемTrue. - Если нет, добавляем текущий индекс в множество
visitedи переходим к следующему элементу, используя значение из спискаhead.
- Если текущий элемент уже встречался (он присутствует в множестве
- Обработка хвоста с циклом: Если мы дошли до конца списка (индекс
-1) иpos != -1, это значит, что в списке есть цикл, и мы должны перенаправить хвост на указанный элемент (индексpos). В таком случае мы "замкнем" список, и процесс будет продолжаться до тех пор, пока не встретим повторяющийся элемент, указывающий на цикл. - Возврат результата: Если мы обошли весь список и не нашли цикл, возвращаем
False.
Пример 1:
Ввод:
head = [3, 2, 0, -4]
pos = 1Разбор:
- Сначала мы проходим по индексу 0, который указывает на 3. Этот индекс добавляется в множество
visited. - Переходим по индексу 3, который указывает на -4. Этот индекс тоже добавляется в множество
visited. - Двигаемся к индексу -1 (конец списка), но так как
pos = 1, то хвост списка теперь указывает обратно на 1-й элемент. - Следовательно, после возвращения к индексу 1, мы видим, что он уже встречался, что указывает на наличие цикла.
- Возвращаем
True.
Вывод:
TrueПример 2:
Ввод:
head = [1, 2]
pos = 0Разбор:
- Мы начинаем с индекса 0, который указывает на 1. Этот индекс добавляется в множество
visited. - Переходим к индексу 1, который указывает на 2. Этот индекс также добавляется в множество
visited. - Двигаемся к индексу -1 (конец списка), но так как
pos = 0, хвост списка снова указывает на 0. - Возвращаемся к индексу 0, который уже встречался, что указывает на наличие цикла.
- Возвращаем
True.
Вывод:
TrueПример 3:
Ввод:
head = [1]
pos = -1Разбор:
- У нас есть только один элемент, который указывает на -1 (конец списка).
- Поскольку
pos = -1, цикл не создается. - В результате возвращаем
False.
Вывод:
False
Вы должны Войти или Зарегистрироваться чтобы оставлять комментарии