#python #python-3.x #linked-list #palindrome
Вопрос:
def is_palindromic_linked_list(head):
if head is None or head.next is None:
return True
slow = head
fast = head
while fast is not None and fast.next is not None:
fast = fast.next.next
slow = slow.next
head_second_half = reverse(slow) #6, 4, 2 => 2, 4, 6
copy_head_second_half = head_second_half #<------HERE: copied linkedlist
while (head is not None and head_second_half is not None):
if head.value != head_second_half.value:
break
head = head.next
head_second_half = head_second_half.next
reverse(copy_head_second_half) #<---HERE: reversed the copied version of the linkedlist to set it back to how it was.
if head is None or head_second_half is None:
return True
return False
def reverse(head):
prev = None
while (head is not None):
next = head.next
head.next = prev
prev = head
head = next
return prev
как в этом есть какой-то смысл? Работает ли связанный список иначе, чем переменные, в которых изменение скопированной версии изменяет оригинал?
Комментарии:
1. В большинстве случаев назначение не создает копию.
2. Связанный список не копируется, только ссылка на связанный список. Существует только 1 связанный список, но 2 переменные, которые указывают на него.
Ответ №1:
Проблема возникает, когда в игру вступают изменяемые объекты. В вашем случае вы ссылаетесь на один и тот же объект, а это означает, что каждая метка указывает на один и тот же объект. На эту тему слишком много можно сказать, но я предлагаю прочитать что-нибудь, начиная отсюда
Ответ №2:
Когда вы напрямую назначаете исходный список списку копирования, вы ссылаетесь на него.
Вам нужно использовать функцию copy(), в зависимости от того, есть ли в вашем списке другие объекты, вам, возможно, придется использовать функцию deepCopy (), все это объясняется в ссылке.
Использование с вашим примером:
- мелкая копия
Неглубокая копия создает новый составной объект, а затем (насколько это возможно) вставляет в него ссылки на объекты, найденные в оригинале.
copy_head_second_half = head_second_half.copy() #<------HERE: copied linkedlist
- Глубокое копирование
Глубокая копия создает новый составной объект, а затем рекурсивно вставляет в него копии объектов, найденных в оригинале.
copy_head_second_half = head_second_half.deepCopy() #<------HERE: copied linkedlist
Ответ №3:
Как уже отмечалось, copy_head_second_half
переменная получает ссылку на головной узел перевернутого связанного списка. Никакие узлы не копируются. Но , пожалуйста, обратите внимание, что список уже мутирован reverse
, поэтому, даже если бы вы думали, что копируете список с этим заданием, это произошло бы слишком поздно: мутация исходного списка уже произошла.
Вам нужна эта copy_head_second_half
переменная не потому, что вам нужна копия всего списка, а потому, что вам нужно сохранить ссылку на этот головной узел, пока head_second_half
он будет указывать на другие узлы в следующем цикле. Без этой скопированной ссылки вы бы потеряли, с чего начинался этот второй список!
Верно, исходный список мутирует при вызове reverse
, но именно поэтому ваш код вызывает reverse
снова: таким образом, мутация будет отменена, и ваш список вернется в исходное состояние, когда функция вернется.
На самом деле это хорошая практика: вы не выделяете память для создания копии половины списка.