Это является частью серии объяснений решения LeetCode ( index ). Если вам понравилось это решение или нашел его полезным, Пожалуйста, как Этот пост и/или УПОТАТЬ Мое решение пост на форумах LeetCode Отказ
Проблема летакода # 234 (Легко): Палиндром связан список
Описание:
( Перейти к : Идея решения Код : JavaScript | Python |. Java |. C ++
Учитывая голова
отдельно связанного списка, возврат истинный
Если это палиндром.
Примеры:
Вход: | голова = [1,2,2,1] |
Выход: | истинный |
Визуальный |
Вход: | голова = [ 1,2] |
Выход: | ложный |
Визуальный |
Ограничения:
- Количество узлов в списке находится в диапазоне
[1, 10^5]
. 0.Паль
Идея:
( Перейти к : Описание проблемы Код : JavaScript | Python |. Java |. C ++
Наивный подход здесь будет проходить через связанный список и создать массив его значений, а затем сравнить массив к его обратному, чтобы узнать, если это палиндром. Хотя это достаточно легко для достижения, мы бросили сомнение, чтобы найти подход с Космическая сложность только O (1) при сохранении Сложность времени O (n) Отказ
Единственный способ проверить на палиндром в O (1) Пространство потребует, чтобы мы могли получить доступ к оба узлам для сравнения одновременно, а не хранить значения для более позднего сравнения. Казалось бы, это будет проблемой, поскольку связанный список только способствует путешествию в одном направлении.
Но что, если это не сделало?
Ответ – это обратить вспять половину связанного списка, чтобы иметь Следующий Обратите внимание на предыдущий узел вместо следующего узла. ( Примечание. Мы можем вместо этого добавить атрибут ** Prev *, когда мы повторяем через связанный список, а не перезаписывать Далее на задней половине, но это технически использовать o (n) Extra Пространство , как будто мы создали внешний массив значений узла. *)
Затем первая проблема становится поиском середины связанного списка, чтобы начать наш процесс реверсива. Для этого мы можем посмотреть на Алгоритм обнаружения цикла Флойда Отказ
С Флойдом мы пройдем через связанный список с Два указателя Один из которых движется в два раза быстрее, чем другой. Когда быстро Указатель достигает конца списка, медленно Указатель должен тогда быть в середине. С медленно Теперь посередине мы можем перевернуть заднюю половину списка с помощью другой переменной, чтобы содержать ссылку на предыдущий узел ( Prev ) и трехсторонний обмен. Однако прежде чем мы сделаем это, мы захочем установить Preved.next Так что мы нарушаем обратный цикл и избегайте бесконечного цикла. Как только возвращаемая половина правильно обращается и медленно Еще раз в конце списка мы можем начать быстро снова снова на голова и сравните две половины одновременно, без необходимости дополнительного пространства. Если два указателя когда-либо не согласны, мы можем Вернуть ложь иначе мы можем вернуть правда Если оба указателя достигают среднего успеха.
( Примечание. Этот процесс работает независимо от того, является ли длина связанного списка нечетной или даже, поскольку сравнение остановится, когда медленные достигает узла «тупик». )
Реализация:
Код для всех четырех языков практически идентичен.
Код JavaScript:
( Перейти к : Описание проблемы Идея решения
var isPalindrome = function(head) { let slow = head, fast = head, prev, temp while (fast && fast.next) slow = slow.next, fast = fast.next.next prev = slow, slow = slow.next, prev.next = null while (slow) temp = slow.next, slow.next = prev, prev = slow, slow = temp fast = head, slow = prev while (slow) if (fast.val !== slow.val) return false else fast = fast.next, slow = slow.next return true };
Код Python:
( Перейти к : Описание проблемы Идея решения
class Solution: def isPalindrome(self, head: ListNode) -> bool: slow, fast, prev = head, head, None while fast and fast.next: slow, fast = slow.next, fast.next.next prev, slow, prev.next = slow, slow.next, None while slow: temp = slow.next slow.next, prev, slow = prev, slow, temp fast, slow = head, prev while slow: if fast.val != slow.val: return False fast, slow = fast.next, slow.next return True
Java код:
( Перейти к : Описание проблемы Идея решения
class Solution { public boolean isPalindrome(ListNode head) { ListNode slow = head, fast = head, prev, temp; while (fast != null && fast.next != null) { slow = slow.next; fast = fast.next.next; } prev = slow; slow = slow.next; prev.next = null; while (slow != null) { temp = slow.next; slow.next = prev; prev = slow; slow = temp; } fast = head; slow = prev; while (slow != null) { if (fast.val != slow.val) return false; fast = fast.next; slow = slow.next; } return true; } }
C ++ код:
( Перейти к : Описание проблемы Идея решения
class Solution { public: bool isPalindrome(ListNode* head) { ListNode *slow = head, *fast = head, *prev, *temp; while (fast && fast->next) slow = slow->next, fast = fast->next->next; prev = slow, slow = slow->next, prev->next = NULL; while (slow) temp = slow->next, slow->next = prev, prev = slow, slow = temp; fast = head, slow = prev; while (slow) if (fast->val != slow->val) return false; else fast = fast->next, slow = slow->next; return true; } };
Оригинал: “https://dev.to/seanpgallivan/solution-palindrome-linked-list-5721”